Index: webapp/cms/plugins/ugc/i18n/messages_en.xml
===================================================================
--- webapp/cms/plugins/ugc/i18n/messages_en.xml	(revision 0)
+++ webapp/cms/plugins/ugc/i18n/messages_en.xml	(revision 0)
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2010 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+   
+   <!-- TODO : translate -->
+   
+<catalogue xml:lang="fr">
+	<!-- +
+		 | SERVICE
+		 + -->
+    <message key="PLUGINS_UGC_SERVICE_LABEL">UGC</message>
+    <message key="PLUGINS_UGC_SERVICE_HINT">Permet de laisser vos visiteurs proposer du contenu</message>
+    <message key="PLUGINS_UGC_SERVICE_PARAMETER_NAME">Nom du service</message>
+    <message key="PLUGINS_UGC_SERVICE_PARAMETER_NAME_HINT">Nom du service permettant un tri plus efficace de l'ensemble des contenus proposés</message>
+    <message key="PLUGINS_UGC_SERVICE_PARAMETER_WIDTH">Largeur</message>
+    <message key="PLUGINS_UGC_SERVICE_PARAMETER_WIDTH_HINT">Largeur du contenu</message>
+    <message key="PLUGINS_UGC_SERVICE_PARAMETER_MAIL_NOTIFICATION">Email du valideur</message>
+    <message key="PLUGINS_UGC_SERVICE_PARAMETER_MAIL_NOTIFICATION_HINT">Email d'un contributeur chargé de valider les contenus proposés</message>
+    <!-- +
+		 | FORM
+		 + -->
+    <message key="PLUGINS_UGC_SERVICE_FORM_AUTHOR_NAME_LABEL">Nom :</message>
+    <message key="PLUGINS_UGC_SERVICE_FORM_AUTHOR_EMAIL_LABEL">Email :</message>
+    <message key="PLUGINS_UGC_SERVICE_FORM_AUTHOR_COMMENT_LABEL">Commentaire :</message>
+    <message key="PLUGINS_UGC_SERVICE_FORM_BUTTON_CONTENT_LABEL">Editer contenu</message>
+    <message key="PLUGINS_UGC_SERVICE_CONTENT_LABEL">Contenu :</message>
+    <message key="PLUGINS_UGC_SERVICE_TITLE_LABEL">Titre :</message>
+    <message key="PLUGINS_UGC_SERVICE_FORM_BUTTON_SUBMIT_LABEL">Proposer</message>
+    <message key="PLUGINS_UGC_SERVICE_FORM_POPUP_BLOQUED">Ce service ne peut fonctionner correctement si votre navigateur bloque les fenêtres pop-up.</message>
+    
+    
+	<!-- +
+		 | MAIL
+		 + -->
+    <message key="PLUGINS_UGC_MAIL_BODY_CONTRIB_NEW_CONTENT">L'utilisateur {0} a proposé un contenu intitulé "{1}" sur le service "{2}" pour le site "{3}".&#13;Commentaire : {4}&#13;Contact : {5}&#13;Vous pouvez dès à présent le consulter avec l'outil de recherche de contenu d'Ametys.</message>
+    <message key="PLUGINS_UGC_MAIL_BODY_AUTHOR_NEW_CONTENT">Bonjour {0},&#13;Nous avons bien reçu votre proposition de contenu intitulée "{1}" pour le site "{2}". Nous mettons tout en oeuvre pour la traiter le plus rapidement possible.&#13;Cordialement,&#13;L'équipe</message>
+    <message key="PLUGINS_UGC_MAIL_SUBJECT_CONTRIB_NEW_CONTENT">Nouveau contenu proposé pour "{0}" de {1}</message>
+    <message key="PLUGINS_UGC_MAIL_SUBJECT_AUTHOR_NEW_CONTENT">Confirmation de proposition de contenu pour le site "{0}"</message>
+
+	<!-- +
+		 | SUBMIT AND ERRORS
+		 + -->
+	<message key="PLUGINS_UGC_SERVICE_FORM_SUBMIT_ACCEPT_MESSAGE">Votre contenu a bien été validé, un contributeur est prévenu.</message>
+    <message key="PLUGINS_UGC_SERVICE_FORM_SUBMIT_REFUSE_MESSAGE">Votre contenu n'a pas été validé.</message>
+    <message key="PLUGINS_UGC_SERVICE_LINK">Proposer un contenu</message>
+    <message key="PLUGINS_UGC_SUBMIT_ERROR_NAME">Vous devez saisir votre nom</message>
+    <message key="PLUGINS_UGC_SUBMIT_ERROR_EMAIL">L'adresse email saisie n'est pas valide</message>
+    <message key="PLUGINS_UGC_SUBMIT_ERROR_CONTENT">Votre contenu est vide</message>
+    <message key="PLUGINS_UGC_SUBMIT_ERROR_CONTENT_INVALID">Votre contenu ne contient pas de texte</message>
+    <message key="PLUGINS_UGC_SUBMIT_ERROR_TITLE">Votre titre est vide</message>
+    <message key="PLUGINS_UGC_SUBMIT_ERROR_CAPTCHA">Les lettres figurant dans l'image ne correspondent pas aux lettres que vous avez saisi</message>
+	<message key="PLUGINS_UGC_SUBMIT_PAGE_ERROR_TITLE">Erreur sur votre contenu</message>
+	<message key="PLUGINS_UGC_SUBMIT_PAGE_ERROR_DESCRIPTION">Votre contenu contient les erreurs suivantes :</message>
+	<message key="PLUGINS_UGC_SUBMIT_PAGE_ERROR_BACK_ALT">Utilisez le bouton 'Précédent' de votre navigateur web pour corriger votre contenu.</message>
+	<message key="PLUGINS_UGC_SUBMIT_PAGE_ERROR_BACK">Cliquez ici pour corriger votre contenu.</message>
+    <message key="PLUGINS_UGC_SUBMIT_PAGE_SUCCESS_TITLE">Contenu suggéré</message>
+    <message key="PLUGINS_UGC_SUBMIT_PAGE_SUCCESS_DESCRIPTION1">Votre contenu a bien été suggéré.</message>
+    <message key="PLUGINS_UGC_SUBMIT_PAGE_SUCCESS_DESCRIPTION2">Merci pour votre contribution.</message>
+    <message key="PLUGINS_UGC_SUBMIT_PAGE_SUCCESS_BACK">Retourner à la page précédente</message>
+    
+    <!-- +
+		 | CONTENT-TYPE
+		 + -->
+    <message key="PLUGINS_UGC_CONTENT_LABEL">Contenu simple</message>
+    <message key="PLUGINS_UGC_CONTENT_DESCRIPTION">Contenu simple proposé par des visiteurs via le service UGC</message>
+    <message key="PLUGINS_UGC_CONTENT_TITLE">Titre</message>
+    <message key="PLUGINS_UGC_CONTENT_TITLE_DESC">Titre du contenu</message>
+    <message key="PLUGINS_UGC_CONTENT_ILLUSTRATION">Illustration</message>
+    <message key="PLUGINS_UGC_CONTENT_ILLUSTRATION_DESC">Image ou texte illustrant le contenu</message>
+    <message key="PLUGINS_UGC_CONTENT_IMAGE">Image</message>
+    <message key="PLUGINS_UGC_CONTENT_IMAGE_DESC">Image</message>
+    <message key="PLUGINS_UGC_CONTENT_IMAGE_ALT">Alternative</message>
+    <message key="PLUGINS_UGC_CONTENT_IMAGE_ALT_DESC">Texte alternatif de l'image</message>
+    <message key="PLUGINS_UGC_CONTENT_CONTENT">Contenu</message>
+    <message key="PLUGINS_UGC_CONTENT_CONTENT_DESC">Le contenu</message>
+    <message key="PLUGINS_UGC_CONTENT_AUTHOR">Auteur</message>
+    <message key="PLUGINS_UGC_CONTENT_AUTHOR_DESC">Auteur de l'article</message>
+    <message key="PLUGINS_UGC_CONTENT_AUTHOR_NAME">Nom</message>
+    <message key="PLUGINS_UGC_CONTENT_AUTHOR_NAME_DESC">Nom de l'auteur</message>
+    <message key="PLUGINS_UGC_CONTENT_AUTHOR_MAIL">Mail</message>
+    <message key="PLUGINS_UGC_CONTENT_AUTHOR_MAIL_DESC">Mail de l'auteur</message>
+    <message key="PLUGINS_UGC_CONTENT_COMMENT">Commentaire</message>
+    <message key="PLUGINS_UGC_CONTENT_COMMENT_DESC">Le commentaire laissé par l'auteur sur son contenu</message>
+    
+    <!-- +
+		 | CONTENT-VIEW
+		 + -->
+    <message key="PLUGINS_UGC_VIEW_MAIN">Complète</message>
+    <message key="PLUGINS_UGC_VIEW_ABSTRACT">Résumé</message>
+    <message key="PLUGINS_UGC_VIEW_LINK">Lien</message>
+    
+</catalogue>
Index: webapp/cms/plugins/ugc/i18n/messages_fr.xml
===================================================================
--- webapp/cms/plugins/ugc/i18n/messages_fr.xml	(revision 0)
+++ webapp/cms/plugins/ugc/i18n/messages_fr.xml	(revision 0)
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2010 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+<catalogue xml:lang="fr">
+
+	<!-- +
+		 | SERVICE
+		 + -->
+    <message key="PLUGINS_UGC_SERVICE_LABEL">UGC</message>
+    <message key="PLUGINS_UGC_SERVICE_HINT">Permet de laisser vos visiteurs proposer du contenu</message>
+    <message key="PLUGINS_UGC_SERVICE_PARAMETER_NAME">Nom du service</message>
+    <message key="PLUGINS_UGC_SERVICE_PARAMETER_NAME_HINT">Nom du service permettant un tri plus efficace de l'ensemble des contenus proposés</message>
+    <message key="PLUGINS_UGC_SERVICE_PARAMETER_WIDTH">Largeur</message>
+    <message key="PLUGINS_UGC_SERVICE_PARAMETER_WIDTH_HINT">Largeur du contenu</message>
+    <message key="PLUGINS_UGC_SERVICE_PARAMETER_MAIL_NOTIFICATION">Email du valideur</message>
+    <message key="PLUGINS_UGC_SERVICE_PARAMETER_MAIL_NOTIFICATION_HINT">Email d'un contributeur chargé de valider les contenus proposés</message>
+  
+    <!-- +
+		 | FORM
+		 + -->
+    <message key="PLUGINS_UGC_SERVICE_FORM_AUTHOR_NAME_LABEL">Nom :</message>
+    <message key="PLUGINS_UGC_SERVICE_FORM_AUTHOR_EMAIL_LABEL">Email :</message>
+    <message key="PLUGINS_UGC_SERVICE_FORM_AUTHOR_COMMENT_LABEL">Commentaire :</message>
+    <message key="PLUGINS_UGC_SERVICE_FORM_BUTTON_CONTENT_LABEL">Ouvrir un éditeur de contenu</message>
+    <message key="PLUGINS_UGC_SERVICE_CONTENT_LABEL">Contenu :</message>
+    <message key="PLUGINS_UGC_SERVICE_TITLE_LABEL">Titre :</message>
+    <message key="PLUGINS_UGC_SERVICE_FORM_BUTTON_SUBMIT_LABEL">Proposer</message>
+    <message key="PLUGINS_UGC_SERVICE_FORM_POPUP_BLOQUED_1">Il semblerait que votre navigateur bloque les fenêtres pop-up.</message>
+    <message key="PLUGINS_UGC_SERVICE_FORM_POPUP_BLOQUED_2">Veuillez autoriser les fenêtres pop-up pour pouvoir utiliser correctement ce service.</message>
+    
+	<!-- +
+		 | MAIL
+		 + -->
+    <message key="PLUGINS_UGC_MAIL_BODY_CONTRIB_NEW_CONTENT">L'utilisateur {0} a proposé un contenu intitulé "{1}" sur le service "{2}" pour le site "{3}".&#13;Commentaire : {4}&#13;Contact : {5}&#13;Vous pouvez dès à présent le consulter avec l'outil de recherche de contenu d'Ametys.</message>
+    <message key="PLUGINS_UGC_MAIL_BODY_AUTHOR_NEW_CONTENT">Bonjour {0},&#13;Nous avons bien reçu votre proposition de contenu intitulée "{1}" pour le site "{2}". Nous mettons tout en oeuvre pour la traiter le plus rapidement possible.&#13;Cordialement,&#13;L'équipe</message>
+    <message key="PLUGINS_UGC_MAIL_SUBJECT_CONTRIB_NEW_CONTENT">Nouveau contenu proposé pour "{0}" de {1}</message>
+    <message key="PLUGINS_UGC_MAIL_SUBJECT_AUTHOR_NEW_CONTENT">Confirmation de proposition de contenu pour le site "{0}"</message>
+
+	<!-- +
+		 | SUBMIT AND ERRORS
+		 + -->
+	<message key="PLUGINS_UGC_SERVICE_FORM_SUBMIT_ACCEPT_MESSAGE">Votre contenu a bien été validé, un contributeur est prévenu.</message>
+    <message key="PLUGINS_UGC_SERVICE_FORM_SUBMIT_REFUSE_MESSAGE">Votre contenu n'a pas été validé.</message>
+    <message key="PLUGINS_UGC_SERVICE_LINK">Proposer un contenu</message>
+    <message key="PLUGINS_UGC_SUBMIT_ERROR_NAME">Vous devez saisir votre nom</message>
+    <message key="PLUGINS_UGC_SUBMIT_ERROR_EMAIL">L'adresse email saisie n'est pas valide</message>
+    <message key="PLUGINS_UGC_SUBMIT_ERROR_CONTENT">Votre contenu est vide</message>
+    <message key="PLUGINS_UGC_SUBMIT_ERROR_CONTENT_INVALID">Votre contenu ne contient pas de texte</message>
+    <message key="PLUGINS_UGC_SUBMIT_ERROR_TITLE">Votre titre est vide</message>
+    <message key="PLUGINS_UGC_SUBMIT_ERROR_CAPTCHA">Les lettres figurant dans l'image ne correspondent pas aux lettres que vous avez saisi</message>
+	<message key="PLUGINS_UGC_SUBMIT_PAGE_ERROR_TITLE">Erreur sur votre contenu</message>
+	<message key="PLUGINS_UGC_SUBMIT_PAGE_ERROR_DESCRIPTION">Votre contenu contient les erreurs suivantes :</message>
+	<message key="PLUGINS_UGC_SUBMIT_PAGE_ERROR_BACK_ALT">Utilisez le bouton 'Précédent' de votre navigateur web pour corriger votre contenu.</message>
+	<message key="PLUGINS_UGC_SUBMIT_PAGE_ERROR_BACK">Cliquez ici pour corriger votre contenu.</message>
+    <message key="PLUGINS_UGC_SUBMIT_PAGE_SUCCESS_TITLE">Contenu suggéré</message>
+    <message key="PLUGINS_UGC_SUBMIT_PAGE_SUCCESS_DESCRIPTION1">Votre contenu a bien été suggéré.</message>
+    <message key="PLUGINS_UGC_SUBMIT_PAGE_SUCCESS_DESCRIPTION2">Merci pour votre contribution.</message>
+    <message key="PLUGINS_UGC_SUBMIT_PAGE_SUCCESS_BACK">Retourner à la page précédente</message>
+    
+    <!-- +
+		 | CONTENT-TYPE
+		 + -->
+    <message key="PLUGINS_UGC_CONTENT_LABEL">Contenu simple</message>
+    <message key="PLUGINS_UGC_CONTENT_DESCRIPTION">Contenu simple proposé par des visiteurs via le service UGC</message>
+    <message key="PLUGINS_UGC_CONTENT_TITLE">Titre</message>
+    <message key="PLUGINS_UGC_CONTENT_TITLE_DESC">Titre du contenu</message>
+    <message key="PLUGINS_UGC_CONTENT_ILLUSTRATION">Illustration</message>
+    <message key="PLUGINS_UGC_CONTENT_ILLUSTRATION_DESC">Image ou texte illustrant le contenu</message>
+    <message key="PLUGINS_UGC_CONTENT_IMAGE">Image</message>
+    <message key="PLUGINS_UGC_CONTENT_IMAGE_DESC">Image</message>
+    <message key="PLUGINS_UGC_CONTENT_IMAGE_ALT">Alternative</message>
+    <message key="PLUGINS_UGC_CONTENT_IMAGE_ALT_DESC">Texte alternatif de l'image</message>
+    <message key="PLUGINS_UGC_CONTENT_CONTENT">Contenu</message>
+    <message key="PLUGINS_UGC_CONTENT_CONTENT_DESC">Le contenu</message>
+    <message key="PLUGINS_UGC_CONTENT_AUTHOR">Auteur</message>
+    <message key="PLUGINS_UGC_CONTENT_AUTHOR_DESC">Auteur de l'article</message>
+    <message key="PLUGINS_UGC_CONTENT_AUTHOR_NAME">Nom</message>
+    <message key="PLUGINS_UGC_CONTENT_AUTHOR_NAME_DESC">Nom de l'auteur</message>
+    <message key="PLUGINS_UGC_CONTENT_AUTHOR_MAIL">Mail</message>
+    <message key="PLUGINS_UGC_CONTENT_AUTHOR_MAIL_DESC">Mail de l'auteur</message>
+    <message key="PLUGINS_UGC_CONTENT_COMMENT">Commentaire</message>
+    <message key="PLUGINS_UGC_CONTENT_COMMENT_DESC">Le commentaire laissé par l'auteur sur son contenu</message>
+    
+    <!-- +
+		 | CONTENT-VIEW
+		 + -->
+    <message key="PLUGINS_UGC_VIEW_MAIN">Complète</message>
+    <message key="PLUGINS_UGC_VIEW_ABSTRACT">Résumé</message>
+    <message key="PLUGINS_UGC_VIEW_LINK">Lien</message>
+    
+</catalogue>
Index: webapp/cms/plugins/ugc/pages/errors2i18n.xsl
===================================================================
--- webapp/cms/plugins/ugc/pages/errors2i18n.xsl	(revision 0)
+++ webapp/cms/plugins/ugc/pages/errors2i18n.xsl	(revision 0)
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2010 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+<xsl:stylesheet version="1.0" 
+	xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
+	xmlns:i18n="http://apache.org/cocoon/i18n/2.1">
+	
+	<xsl:template match="/ActionResult">
+		<ActionResult>
+			<xsl:copy-of select="*[local-name() != 'errors']"/>
+			
+			<xsl:if test="string-length(errors) &gt; 0">
+				<errors>
+					<xsl:call-template name="error">
+						<xsl:with-param name="error" select="errors"/>
+					</xsl:call-template>
+				</errors>
+			</xsl:if>
+		</ActionResult> 
+	</xsl:template>
+	
+	<xsl:template name="error">
+		<xsl:param name="error"/>
+		
+		<xsl:choose>
+			<xsl:when test="substring-before($error, ';') != ''">
+				<xsl:variable name="fullkey" select="substring-before($error, ';')"/>
+				<error><i18n:text i18n:key="{substring-after($fullkey, ':')}" i18n:catalogue="{substring-before($fullkey, ':')}"/></error>
+				<xsl:call-template name="error">
+					<xsl:with-param name="error" select="substring-after($error, ';')"/>
+				</xsl:call-template>
+			</xsl:when>
+			<xsl:when test="string-length($error) &gt; 0">
+				<error><i18n:text i18n:key="{substring-after($error, ':')}" i18n:catalogue="{substring-before($error, ':')}"/></error>
+			</xsl:when>
+		</xsl:choose>
+	
+	</xsl:template>
+	
+</xsl:stylesheet>
\ No newline at end of file
Index: webapp/cms/plugins/ugc/pages/presentation.xsl
===================================================================
--- webapp/cms/plugins/ugc/pages/presentation.xsl	(revision 0)
+++ webapp/cms/plugins/ugc/pages/presentation.xsl	(revision 0)
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2010 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+<xsl:stylesheet version="1.0" 
+	xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
+	xmlns:i18n="http://apache.org/cocoon/i18n/2.1">
+	
+	<xsl:template match="/ActionResult">
+		<html>
+			<head/>
+			<body id="default">
+				<xsl:choose>
+					<xsl:when test="errors">
+						<div class="submit-errors">
+							<h1><i18n:text i18n:key="PLUGINS_UGC_SUBMIT_PAGE_ERROR_TITLE" i18n:catalogue="plugin.ugc"/></h1>
+							<p><i18n:text i18n:key="PLUGINS_UGC_SUBMIT_PAGE_ERROR_DESCRIPTION" i18n:catalogue="plugin.ugc"/></p>
+							<ul class="errors">
+								<xsl:for-each select="errors/error">
+									<li class="error"><xsl:value-of select="."/></li>
+								</xsl:for-each>
+							</ul>
+							<noscript>
+								<p><i18n:text i18n:key="PLUGINS_UGC_SUBMIT_PAGE_ERROR_BACK_ALT" i18n:catalogue="plugin.ugc"/></p>
+							</noscript>
+							<script type="text/javascript">
+								document.write("&lt;p&gt;&lt;a href='javascript: history.back();'&gt;<i18n:text i18n:key="PLUGINS_UGC_SUBMIT_PAGE_ERROR_BACK" i18n:catalogue="plugin.ugc"/>&lt;/a&gt;&lt;/p&gt;")
+							</script>
+						</div>
+					</xsl:when>
+					<xsl:otherwise>
+						<div class="submit-success">
+							<h1><i18n:text i18n:key="PLUGINS_UGC_SUBMIT_PAGE_SUCCESS_TITLE" i18n:catalogue="plugin.ugc"/></h1>
+							<p><i18n:text i18n:key="PLUGINS_UGC_SUBMIT_PAGE_SUCCESS_DESCRIPTION1" i18n:catalogue="plugin.ugc"/></p>
+							<p><i18n:text i18n:key="PLUGINS_UGC_SUBMIT_PAGE_SUCCESS_DESCRIPTION2" i18n:catalogue="plugin.ugc"/></p>
+							<xsl:if test="string-length(redirect) &gt; 0">
+								<p><a href="{redirect}"><i18n:text i18n:key="PLUGINS_UGC_SUBMIT_PAGE_SUCCESS_BACK" i18n:catalogue="plugin.ugc"/></a></p>
+							</xsl:if>
+						</div>
+					</xsl:otherwise>
+				</xsl:choose>
+			</body>
+		</html>
+	</xsl:template>
+	
+</xsl:stylesheet>
\ No newline at end of file
Index: webapp/cms/plugins/ugc/pages/services/ugc/ugc.xsl
===================================================================
--- webapp/cms/plugins/ugc/pages/services/ugc/ugc.xsl	(revision 0)
+++ webapp/cms/plugins/ugc/pages/services/ugc/ugc.xsl	(revision 0)
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2010 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+<xsl:stylesheet version="1.0" 
+	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+	xmlns:i18n="http://apache.org/cocoon/i18n/2.1" 
+    xmlns:ametys="org.ametys.web.transformation.xslt.AmetysXSLTHelper"
+	xmlns:math="http://exslt.org/math" 
+	exclude-result-prefixes="math">
+	
+	<xsl:import href="plugin:cms://stylesheets/helper/common.xsl"/>
+	
+	<xsl:param name="contextPath"/>
+	<xsl:variable name="siteName" select="ametys:site()"/>
+	<xsl:variable name="locale" select="ametys:lang()"/>
+	<xsl:variable name="uri-prefix" select="ametys:uriPrefix()"/>
+	<xsl:variable name="width" select="ametys:serviceParameter('width')"/>
+	<xsl:variable name="ugcName" select="ametys:serviceParameter('ugcName')"/>
+	<xsl:variable name="mailNotification" select="ametys:serviceParameter('mailNotification')"/>
+	<xsl:variable name="uniqueId" select="substring-after(math:random(), '.')"/>
+
+	<xsl:template match="/">
+		<html>
+			<header>
+				<title></title>
+			</header>
+			<body>
+				<xsl:call-template name="ugc-form"/>
+				<xsl:call-template name="ugc-form-js"/>
+			</body>
+		</html>
+	</xsl:template>	
+
+	<xsl:template name="ugc-form">
+		<form  method="post" id="comment-{$uniqueId}" action="{$uri-prefix}/{$siteName}/{$locale}/_plugins/ugc/page/add-ugc">
+			<xsl:call-template name="ugc-form-popup-bloqued"/>
+			<xsl:call-template name="ugc-form-name"/>
+			<xsl:call-template name="ugc-form-email"/>
+			<xsl:call-template name="ugc-form-title"/>
+			<xsl:call-template name="ugc-form-content"/>
+			<xsl:call-template name="ugc-form-comment"/>
+			<xsl:call-template name="ugc-form-captcha"/>
+			<xsl:call-template name="ugc-form-submit"/>
+			<xsl:call-template name="ugc-form-hidden"/>
+		</form>
+	</xsl:template>
+	
+	<xsl:template name="ugc-form-popup-bloqued">
+		<xsl:if test="ametys:renderingContext() != 'back'">
+			<!-- Should works on most navigator, but not chrome -->
+			<script type="text/javascript">
+				document.write("&lt;div id='pop-up-message-<xsl:value-of select="$uniqueId"/>-1' class='error'>&lt;/div>");
+				document.write("&lt;div id='pop-up-message-<xsl:value-of select="$uniqueId"/>-2' class='error'>&lt;/div>");
+				var popup = window.open("about:blank", "popup", "height=1,width=1,left=5000,top=5000,location=no,menubar=no,resizable=no,scrollbars=no,status=no,titlebar=no,toolbar=no");
+				if (!popup || popup.closed || typeof popup == 'undefined' || typeof popup.closed=='undefined')
+			    {
+					jQuery("div#pop-up-message-<xsl:value-of select="$uniqueId"/>-1").text('<i18n:text i18n:key="PLUGINS_UGC_SERVICE_FORM_POPUP_BLOQUED_1" i18n:catalogue="plugin.ugc"/>');
+					jQuery("div#pop-up-message-<xsl:value-of select="$uniqueId"/>-2").text('<i18n:text i18n:key="PLUGINS_UGC_SERVICE_FORM_POPUP_BLOQUED_2" i18n:catalogue="plugin.ugc"/>');
+			    }
+			    if (popup &amp;&amp; popup.close)
+			    {
+			    	popup.close();
+			    }
+			</script>
+		</xsl:if>
+	</xsl:template>
+
+	<xsl:template name="ugc-form-name">
+		<div class="field">
+			<div class="label">
+				<label for="ugc-form-name-{$uniqueId}">
+					<i18n:text i18n:key="PLUGINS_UGC_SERVICE_FORM_AUTHOR_NAME_LABEL" i18n:catalogue="plugin.ugc"/>
+					<xsl:call-template name="comment-form-mandatorymarker"/>	
+				</label>
+			</div>
+			<div class="input">
+				<input type="text" name="authorName" id="ugc-form-name-{$uniqueId}"/>
+			</div>
+			<div class="field-end"></div>
+		</div>
+	</xsl:template>
+
+	<xsl:template name="ugc-form-email">
+		<div class="field">
+			<div class="label">
+				<label for="ugc-form-email-{$uniqueId}">
+					<i18n:text i18n:key="PLUGINS_UGC_SERVICE_FORM_AUTHOR_EMAIL_LABEL" i18n:catalogue="plugin.ugc"/>
+					<xsl:call-template name="comment-form-mandatorymarker"/>
+				</label>
+			</div>
+			<div class="input">
+				<input type="text" name="authorEmail" id="ugc-form-email-{$uniqueId}"/>
+			</div>
+			<div class="field-end"></div>
+		</div>
+	</xsl:template>
+
+	<xsl:template name="ugc-form-title">
+		<noscript>
+			<div id="ugc-form-div-title-{$uniqueId}" class="field">
+				<div class="label">
+					<label for="ugc-form-title-{$uniqueId}">
+						<i18n:text i18n:key="PLUGINS_UGC_SERVICE_TITLE_LABEL" i18n:catalogue="plugin.ugc"/>
+						<xsl:call-template name="comment-form-mandatorymarker"/>
+					</label>
+				</div>
+				<div class="input">
+					<input type="text" id="ugc-form-title-{$uniqueId}" name="title"/>
+				</div>
+				<div class="field-end"></div>
+			</div>
+		</noscript>
+	</xsl:template>
+
+	<xsl:template name="ugc-form-content">
+		<!-- if javascript then display a button to back-office and a preview, else display a textarea -->
+		<div id="ugc-form-div-content-{$uniqueId}" class="field">
+			<div class="label">
+				<label for="ugc-form-textarea-content-{$uniqueId}">
+					<i18n:text i18n:key="PLUGINS_UGC_SERVICE_CONTENT_LABEL" i18n:catalogue="plugin.ugc"/>
+					<xsl:call-template name="comment-form-mandatorymarker"/>
+				</label>
+			</div>
+			<div class="input">
+				<noscript>
+					<textarea id="ugc-form-textarea-content-{$uniqueId}" name="content"/>
+				</noscript>
+				<script type="text/javascript">
+					document.write("&lt;input type='button' id='ugc-form-button-content-<xsl:value-of select="$uniqueId"/>' OnClick='editContentListener_<xsl:value-of select="$uniqueId"/>();' value='<i18n:text i18n:key="PLUGINS_UGC_SERVICE_FORM_BUTTON_CONTENT_LABEL" i18n:catalogue="plugin.ugc"/>'/>");
+				</script>				
+			</div>
+			<div class="field-end"></div>
+		</div>
+		<div id="ugc-form-preview-{$uniqueId}"/>
+	</xsl:template>
+
+	<xsl:template name="ugc-form-comment">
+		<div class="field">
+			<div class="label">
+				<label for="ugc-form-comment-{$uniqueId}">
+					<i18n:text i18n:key="PLUGINS_UGC_SERVICE_FORM_AUTHOR_COMMENT_LABEL" i18n:catalogue="plugin.ugc"/>
+				</label>
+			</div>
+			<div class="input">
+				<textarea name="authorComment" id="ugc-form-comment-{$uniqueId}"/>
+			</div>
+			<div class="field-end"></div>
+		</div>
+	</xsl:template>
+
+	<xsl:template name="ugc-form-captcha">
+		<div class="field">
+			<div class="label">
+				<label for="ugc-captcha-{$uniqueId}">
+					<i18n:text i18n:key="PLUGINS_CMS_CONTENT_COMMENTS_POST_AUTHOR_CAPTCHA" i18n:catalogue="plugin.cms"/>
+					<xsl:call-template name="comment-form-mandatorymarker"/>
+				</label>
+			</div>
+			<div class="input">
+				<xsl:call-template name="captcha">
+					<xsl:with-param name="key-name">captcha-key</xsl:with-param>
+					<xsl:with-param name="key-id">ugc-captcha-key-<xsl:value-of select="$uniqueId"/></xsl:with-param>
+
+					<xsl:with-param name="value-name">captcha-value</xsl:with-param>
+					<xsl:with-param name="value-id">ugc-captcha-<xsl:value-of select="$uniqueId"/></xsl:with-param>
+					<xsl:with-param name="value-style"></xsl:with-param>
+					<xsl:with-param name="value-class"/>
+
+					<xsl:with-param name="image-alt">PLUGINS_CMS_CONTENT_COMMENTS_POST_AUTHOR_CAPTCHA</xsl:with-param>
+					<xsl:with-param name="image-alt-i18n" select="true()"/>
+					<xsl:with-param name="image-alt-catalogue">plugin.cms</xsl:with-param>
+					<xsl:with-param name="image-style"></xsl:with-param>
+					<xsl:with-param name="image-class"/>
+					
+					<xsl:with-param name="js-funcname-torefresh">refresh_ugc_<xsl:value-of select="$uniqueId"/></xsl:with-param>
+				</xsl:call-template> 
+			</div>
+			<div class="field-end"></div>
+		</div>
+	</xsl:template>	
+
+	<xsl:template name="ugc-form-submit">
+		<!-- Submit button depends on javascript-->
+		<div id="ugc-form-div-submit-{$uniqueId}" class="field">
+			<noscript>
+				<input type="submit" value="plugin.ugc:PLUGINS_UGC_SERVICE_FORM_BUTTON_SUBMIT_LABEL" i18n:attr="value"/>			
+			</noscript>	
+			<script type="text/javascript">
+				document.write("&lt;input type='button' id='ugc-form-button-submit-<xsl:value-of select="$uniqueId"/>' OnClick='submitContentListener_<xsl:value-of select="$uniqueId"/>();' value='<i18n:text i18n:key="PLUGINS_UGC_SERVICE_FORM_BUTTON_SUBMIT_LABEL" i18n:catalogue="plugin.ugc"/>'/>");
+			</script>
+		</div>
+	</xsl:template>
+
+	<xsl:template name="ugc-form-hidden">
+		<div class="field">
+			<input type="hidden" id="ugc-form-mail-notification-{$uniqueId}" name="mailNotification" value="{$mailNotification}"/>
+			<input type="hidden" id="ugc-form-ugcName-{$uniqueId}" name="ugcName" value="{$ugcName}"/>
+			<input type="hidden" id="ugc-form-width-{$uniqueId}" name="width" value="{$width}"/>
+			<input type="hidden" id="ugc-form-siteName-{$uniqueId}" name="siteName" value="{$siteName}"/>
+		</div>
+	</xsl:template>
+
+	<xsl:template name="comment-form-mandatorymarker">
+		<span>*</span>
+	</xsl:template>	
+	
+	<xsl:template name="ugc-form-js">
+		<script type="text/javascript">
+			var contentId_<xsl:value-of select="$uniqueId"/> = "";
+			
+			function editContentListener_<xsl:value-of select="$uniqueId"/>()
+			{
+				if(contentId_<xsl:value-of select="$uniqueId"/> == "")
+				{
+					<!-- Create content and open it-->
+					var urlCreateContent = '<xsl:value-of select="$contextPath"/>/plugins/ugc/init-ugc-workflow';
+					var params = {
+						siteName : "<xsl:value-of select="$siteName"/>",
+						ugcName : "<xsl:value-of select="$ugcName"/>"
+						
+					};
+					function createContentCb_<xsl:value-of select="$uniqueId"/>(data)
+					{
+						contentId_<xsl:value-of select="$uniqueId"/> = (jQuery(data).find("contentId").text());
+						openContentEditorDialog_<xsl:value-of select="$uniqueId"/>();
+					}
+					$j.post(urlCreateContent, params, createContentCb_<xsl:value-of select="$uniqueId"/>);
+				}
+				else
+				{
+					openContentEditorDialog_<xsl:value-of select="$uniqueId"/>();
+				}
+			}		
+			
+			function openContentEditorDialog_<xsl:value-of select="$uniqueId"/>()
+			{
+				var urlContentEditor = '<xsl:value-of select="$contextPath"/>/<xsl:value-of select="$siteName"/>/contentEditor.html?contentId=' + contentId_<xsl:value-of select="$uniqueId"/> +'&#38;contentZoneWidth='+"<xsl:value-of select="$width"/>"+'&#38;workflow-action='+'2';
+				
+				<!-- FIXME : if pop-up are bloqued, the preview will be display -->
+				<!-- blocking function -->
+				window.showModalDialog(
+					urlContentEditor,
+					"content-editor-dialog",
+					"dialogWidth:1200px; dialogHeight:800px; dialogLeft:20px; dialogTop:20px; status:yes; resizable:yes; scroll:no;"
+				);
+				<!-- Update preview -->
+				var urlCreateContent = '<xsl:value-of select="$contextPath"/>/plugins/ugc/get-ugc-preview?contentId=' + contentId_<xsl:value-of select="$uniqueId"/> + '&#38;maxCharacters=200';
+				var params = {};
+				$j.post(
+					urlCreateContent,
+					params,
+					function(data){
+               			jQuery("div#ugc-form-preview-<xsl:value-of select="$uniqueId"/>").html(data);
+           			}
+           		);
+			}
+	
+			function submitContentListener_<xsl:value-of select="$uniqueId"/>()
+			{
+				var authorNameInput = document.getElementById('ugc-form-name-<xsl:value-of select="$uniqueId"/>');
+				var authorEmailInput = document.getElementById('ugc-form-email-<xsl:value-of select="$uniqueId"/>');
+				var authorCommentInput = document.getElementById('ugc-form-comment-<xsl:value-of select="$uniqueId"/>');
+				var mailNotificationInput = document.getElementById('ugc-form-mail-notification-<xsl:value-of select="$uniqueId"/>');
+				var ugcName = document.getElementById('ugc-form-ugcName-<xsl:value-of select="$uniqueId"/>');
+				var siteName = document.getElementById('ugc-form-siteName-<xsl:value-of select="$uniqueId"/>');
+				var captchaInput = document.getElementById('ugc-captcha-<xsl:value-of select="$uniqueId"/>');
+				var contentFieldDiv = document.getElementById('ugc-form-div-content-<xsl:value-of select="$uniqueId"/>');
+				var errors = "";
+				if (/^\s*$/.test(authorNameInput.value))
+				{
+					errors += "<i18n:text i18n:key="PLUGINS_UGC_SUBMIT_ERROR_NAME" i18n:catalogue="plugin.ugc"/>" + '\n';
+					authorNameInput.parentNode.parentNode.className = "field error";
+				}
+				else
+				{
+					authorNameInput.parentNode.parentNode.className = "field";
+				}
+				if (!/^[a-z0-9._-]+@[a-z0-9.-]{2,}[.][a-z]{2,3}$/.test(authorEmailInput.value))
+				{
+					errors += "<i18n:text i18n:key="PLUGINS_UGC_SUBMIT_ERROR_EMAIL" i18n:catalogue="plugin.ugc"/>" + '\n';
+					authorEmailInput.parentNode.parentNode.className = "field error";
+				}
+				else
+				{
+					authorEmailInput.parentNode.parentNode.className = "field";
+				}
+				if (contentId_<xsl:value-of select="$uniqueId"/> == "")
+				{
+					errors += "<i18n:text i18n:key="PLUGINS_UGC_SUBMIT_ERROR_CONTENT" i18n:catalogue="plugin.ugc"/>" + '\n';
+					contentFieldDiv.className = "field error";
+				}
+				else
+				{
+					contentFieldDiv.className = "field";
+				}
+				
+				if (!/^[a-z]{6}$/.test(captchaInput.value))
+				{
+					errors += "<i18n:text i18n:key="PLUGINS_UGC_SUBMIT_ERROR_CAPTCHA" i18n:catalogue="plugin.ugc"/>";
+					captchaInput.parentNode.parentNode.className = "field error";
+				}
+				else
+				{
+					captchaInput.parentNode.parentNode.className = "field";
+				}
+				
+	
+				if(errors != "")
+				{
+					alert(errors);
+				}
+				else
+				{
+					function result(data)
+					{
+						var errorText = "";
+						$j('.errors .error', data).each(function () { errorText += $j(this).text() + "\n"; });
+							
+						if(!errorText)
+						{
+							alert("<i18n:text i18n:key="PLUGINS_UGC_SERVICE_FORM_SUBMIT_ACCEPT_MESSAGE"/>");
+							<!-- clear the form  -->
+							jQuery('input#ugc-form-name-<xsl:value-of select="$uniqueId"/>').val("");
+							jQuery('input#ugc-form-email-<xsl:value-of select="$uniqueId"/>').val("");
+							jQuery('textarea#ugc-form-comment-<xsl:value-of select="$uniqueId"/>').val("");
+							jQuery("div#ugc-form-preview-<xsl:value-of select="$uniqueId"/>").html("");
+							urlContentEditor_<xsl:value-of select="$uniqueId"/> = undefined;
+							contentId_<xsl:value-of select="$uniqueId"/> = "";
+						}
+						else
+						{
+							alert(errorText);
+						}
+						refresh_ugc_<xsl:value-of select="$uniqueId"/>();
+					}
+					var data = {
+						contentId : contentId_<xsl:value-of select="$uniqueId"/>,
+						authorComment : authorCommentInput.value,
+						authorName : authorNameInput.value,
+						authorEmail : authorEmailInput.value,
+						mailNotification : "<xsl:value-of select="$mailNotification"/>",
+						ugcName : "<xsl:value-of select="$ugcName"/>",
+						siteName : "<xsl:value-of select="$siteName"/>",
+						title : "defaultTitle" // only to prevent error
+					};
+
+					$j.post("<xsl:value-of select="$uri-prefix"/>/plugins/ugc/add-ugc", data, result);
+				}
+			}
+		</script>
+	</xsl:template>
+</xsl:stylesheet>
Index: webapp/cms/plugins/ugc/plugin.xml
===================================================================
--- webapp/cms/plugins/ugc/plugin.xml	(revision 0)
+++ webapp/cms/plugins/ugc/plugin.xml	(revision 0)
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+   Copyright 2010 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+<plugin xmlns="http://www.ametys.org/schema/plugin"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xmlns:cms="http://www.ametys.org/schema/cms"
+        xsi:schemaLocation="http://www.ametys.org/schema/plugin http://www.ametys.org/schema/plugin-2.0.xsd"
+        runtimeVersion="2.0" version="2.0">
+
+    <extension-points>
+        <extension-point id="org.ametys.plugins.ugc.actions.UGCListenerExtensionPoint"
+        				 class="org.ametys.plugins.ugc.actions.UGCListenerExtensionPoint">
+       		<!-- Extension point to add listeners to the add ugc feature -->
+        </extension-point>
+    </extension-points>
+
+    <feature name="ugc.defaultlistener">
+    	<extensions>
+    		<extension point="org.ametys.plugins.ugc.actions.UGCListenerExtensionPoint" 
+    					id="org.ametys.plugins.ugc.actions.DefaultUGCListener" 
+    					class="org.ametys.plugins.ugc.actions.DefaultUGCListener"/>
+    	</extensions>
+    </feature>
+
+	<feature name="ugc-service">
+		<config></config>
+		<extensions>
+			<extension point="org.ametys.web.service.ServiceExtensionPoint"
+	   				   class="org.ametys.web.service.StaticService"
+	   				   id="org.ametys.plugins.ugc.service.UserGeneratedContent">
+
+				<url>service/ugc.html</url>
+
+                <cacheable>true</cacheable>
+			
+				<label i18n="true">PLUGINS_UGC_SERVICE_LABEL</label>
+				<description i18n="true">PLUGINS_UGC_SERVICE_HINT</description>
+				<thumbnail>
+					<small>img/services/ugc/ugc_16.png</small>
+					<medium>img/services/ugc/ugc_32.png</medium>
+					<large>img/services/ugc/ugc_48.png</large>
+				</thumbnail>
+				<parameters>
+					<parameter name="ugcName" type="string">
+						<label i18n="true">PLUGINS_UGC_SERVICE_PARAMETER_NAME</label>
+						<description i18n="true">PLUGINS_UGC_SERVICE_PARAMETER_NAME_HINT</description>
+					</parameter>
+					<parameter name="width" type="string">
+						<label i18n="true">PLUGINS_UGC_SERVICE_PARAMETER_WIDTH</label>
+						<description i18n="true">PLUGINS_UGC_SERVICE_PARAMETER_WIDTH_HINT</description>
+						<default-value>800</default-value>
+					</parameter>
+					<parameter name="mailNotification" type="string">
+						<label i18n="true">PLUGINS_UGC_SERVICE_PARAMETER_MAIL_NOTIFICATION</label>
+						<description i18n="true">PLUGINS_UGC_SERVICE_PARAMETER_MAIL_NOTIFICATION_HINT</description>
+						<validation>
+			            	<regexp>^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,4}$</regexp>
+			            	<invalidText i18n="true">plugin.core:PLUGINS_CORE_REGEXP_INVALID_MAIL</invalidText>
+		            	</validation>
+					</parameter>
+				</parameters>
+			</extension>
+	 	</extensions>
+	</feature>
+	
+	
+	
+	
+	
+	<feature name="content-type-simple-content">
+		 <extensions>
+			 <extension point="org.ametys.cms.contenttype.ContentTypeExtensionPoint"
+                       id="org.ametys.plugins.ugc.Content.simpleContent"
+                       class="org.ametys.cms.contenttype.DefaultContentType">
+				 <cms:content-type>
+				 	<cms:label i18n="true">PLUGINS_UGC_CONTENT_LABEL</cms:label>
+	                <cms:description i18n="true">PLUGINS_UGC_CONTENT_DESCRIPTION</cms:description>
+	                <cms:icons>
+	                	<cms:small>img/content/simpleContent/icon-small.png</cms:small>
+	                	<cms:medium>img/content/simpleContent/icon-medium.png</cms:medium>
+	                	<cms:large>img/content/simpleContent/icon-large.png</cms:large>
+	                </cms:icons>
+                    
+	               	<cms:metadata name="title" type="string">
+						<label i18n="true">PLUGINS_UGC_CONTENT_TITLE</label>
+						<description i18n="true">PLUGINS_UGC_CONTENT_TITLE_DESC</description>
+						<validation>
+							<mandatory />
+						</validation>
+					</cms:metadata>
+					
+					<cms:metadata name="illustration" type="composite">
+						<label i18n="true">PLUGINS_UGC_CONTENT_ILLUSTRATION</label>
+						<description i18n="true">PLUGINS_UGC_CONTENT_ILLUSTRATION_DESC</description>
+						<cms:metadata name="image" type="file">
+							<label i18n="true">PLUGINS_UGC_CONTENT_IMAGE</label>
+							<description i18n="true">PLUGINS_UGC_CONTENT_IMAGE_DESC</description>
+							<widget>external-or-resource-image</widget>
+						</cms:metadata>
+						<cms:metadata name="alt-text" type="string">
+							<label i18n="true">PLUGINS_UGC_CONTENT_IMAGE_ALT</label>
+							<description i18n="true">PLUGINS_UGC_CONTENT_IMAGE_ALT_DESC</description>
+						</cms:metadata>
+					</cms:metadata>
+					
+					<cms:metadata name="content" type="rich-text">
+						<label i18n="true">PLUGINS_UGC_CONTENT_CONTENT</label>
+						<description i18n="true">PLUGINS_UGC_CONTENT_CONTENT_DESC</description>
+						<validation>
+							<mandatory />
+						</validation>
+					</cms:metadata>
+					
+					<cms:metadata name="comment" type="string">
+						<label i18n="true">PLUGINS_UGC_CONTENT_COMMENT</label>
+						<description i18n="true">PLUGINS_UGC_CONTENT_COMMENT_DESC</description>
+					</cms:metadata>
+					
+					<cms:metadata name="contact" type="composite">
+						<label i18n="true">PLUGINS_UGC_CONTENT_AUTHOR</label>
+						<description i18n="true">PLUGINS_UGC_CONTENT_AUTHOR_DESC</description>
+						<cms:metadata name="name" type="string">
+							<label i18n="true">PLUGINS_UGC_CONTENT_AUTHOR_NAME</label>
+							<description i18n="true">PLUGINS_UGC_CONTENT_AUTHOR_NAME_DESC</description>
+						</cms:metadata>
+						<cms:metadata name="mail" type="string">
+							<label i18n="true">PLUGINS_UGC_CONTENT_AUTHOR_MAIL</label>
+							<description i18n="true">PLUGINS_UGC_CONTENT_AUTHOR_MAIL_DESC</description>
+							<validation>
+								<regexp>^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,4}$</regexp>
+								<invalidText i18n="true">plugin.web:PLUGINS_WEB_REGEXP_INVALID_MAIL</invalidText>
+							</validation>
+						</cms:metadata>
+					</cms:metadata>
+					
+	                <!-- Main -->
+	                <cms:metadata-set name="main" type="view">
+	                	<cms:metadata-ref name="title" />
+						<cms:metadata-ref name="illustration">
+							<cms:metadata-ref name="image" />
+							<cms:metadata-ref name="alt-text" />
+						</cms:metadata-ref>
+						<cms:metadata-ref name="content" />
+						<cms:label i18n="true">PLUGINS_UGC_VIEW_MAIN</cms:label>
+	                </cms:metadata-set>
+	                
+	                <cms:metadata-set name="main" type="edition">
+	                	<cms:metadata-ref name="title" />
+						<cms:metadata-ref name="illustration">
+							<cms:metadata-ref name="image" />
+							<cms:metadata-ref name="alt-text" />
+						</cms:metadata-ref>
+						<cms:metadata-ref name="content" />
+	                </cms:metadata-set>
+	                
+	                <!-- Search -->
+	                <cms:metadata-set name="search" type="view" internal="true">
+	                 	<cms:metadata-ref name="title" />
+	                 </cms:metadata-set>
+	                
+	                <!-- Abstract view -->
+					<cms:metadata-set name="abstract" type="view">
+						<cms:metadata-ref name="title" />
+						<cms:metadata-ref name="illustration">
+							<cms:metadata-ref name="image" />
+							<cms:metadata-ref name="alt-text" />
+						</cms:metadata-ref>
+                        <cms:metadata-ref name="content" />
+						<cms:label i18n="true">PLUGINS_UGC_VIEW_ABSTRACT</cms:label>
+					</cms:metadata-set>
+					
+					<!-- List view -->
+					<cms:metadata-set name="link" type="view">
+						<cms:metadata-ref name="title" />
+						<cms:label i18n="true">PLUGINS_UGC_VIEW_LINK</cms:label>
+					</cms:metadata-set>
+	                
+	                <!-- Details -->
+	                <cms:metadata-set name="details" type="view" internal="true">
+	                	<cms:metadata-ref name="title"/>
+	                	<cms:metadata-ref name="contact">
+							<cms:metadata-ref name="name" />
+							<cms:metadata-ref name="mail" />
+						</cms:metadata-ref>
+						<cms:metadata-ref name="comment" />
+	                </cms:metadata-set>
+
+					<!-- Index -->
+	                <cms:metadata-set name="index" type="view" internal="true">
+	                	<cms:metadata-ref name="title" />
+						<cms:metadata-ref name="illustration">
+							<cms:metadata-ref name="alt-text" />
+						</cms:metadata-ref>
+						<cms:metadata-ref name="content" />
+						<cms:metadata-ref name="contact">
+							<cms:metadata-ref name="name" />
+							<cms:metadata-ref name="mail" />
+						</cms:metadata-ref>
+						<cms:metadata-ref name="comment" />
+	                </cms:metadata-set>
+				 </cms:content-type>
+            </extension>
+		</extensions>
+	</feature>
+	
+	
+	
+	
+	
+</plugin>
\ No newline at end of file
Index: webapp/cms/plugins/ugc/sitemap.xmap
===================================================================
--- webapp/cms/plugins/ugc/sitemap.xmap	(revision 0)
+++ webapp/cms/plugins/ugc/sitemap.xmap	(revision 0)
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2009 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+<map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0">
+	<map:components>
+		<map:actions>
+			<map:action name="init-ugc-workflow-action" src="org.ametys.plugins.ugc.init.InitializeUGCWorkflowAction"/>
+			<map:action name="add-ugc" src="org.ametys.plugins.ugc.actions.AddUGCAction"/>
+		</map:actions>
+		<map:transformers>
+			<map:transformer name="ugc-preview-transformer" src="org.ametys.plugins.ugc.preview.GetUGCPreviewTransformer"/>
+		</map:transformers>
+	</map:components>
+	
+	<map:pipelines>
+       <map:pipeline>     
+            <!-- +
+			     | SITEMAP Service
+			     + -->
+			<map:match pattern="service/ugc.html">
+				<map:generate type="action-result"/>
+				<map:transform type="xslt" src="service://pages/services/ugc/ugc.xsl">
+					<map:parameter name="contextPath" value="{request:contextPath}"/>  
+				</map:transform>
+				<map:transform type="i18n">
+					<map:parameter name="locale" value="{locale:locale}"/>
+					<map:parameter name="plugin" value="{request-attr:pluginName}"/>
+				</map:transform>
+				<map:serialize type="xml"/>
+			</map:match>
+
+			<map:match pattern="get-ugc-preview">
+				<map:generate src="cocoon://_content.html?contentId={request-param:contentId}"/>
+				<map:transform type="ugc-preview-transformer">
+					<map:parameter name="max-characters" value="{request-param:maxCharacters}"/>
+				</map:transform>
+				<map:serialize type="xhtml"/>
+			</map:match>
+			
+			<map:match pattern="init-ugc-workflow">
+				<map:act type="init-ugc-workflow-action">
+					<map:parameter name="lang" value="{locale:locale}"/>
+					<map:generate type="action-result">
+                        <map:parameter name="contentId" value="{contentId}"/>
+                    </map:generate>
+					<map:transform type="i18n">
+						<map:parameter name="locale" value="{locale:locale}"/>
+					</map:transform>
+					<map:serialize type="xml"/>
+				</map:act>
+			</map:match>
+						
+			<!-- Submit action -->
+			<map:match pattern="add-ugc">
+            	<map:act type="add-ugc">
+            		<map:parameter name="lang" value="{locale:locale}"/>
+            		<map:generate type="action-result" label="xml">
+            			<map:parameter name="errors" value="{errors}"/>
+            			<map:parameter name="redirect" value="{redirect}"/>
+            		</map:generate>
+            		<map:transform src="pages/errors2i18n.xsl"/>
+	                <map:transform type="i18n" label="ajax">
+	                    <map:parameter name="locale" value="{locale:locale}"/>
+	                    <map:parameter name="default-catalogue-id" value="plugin.{request-attr:pluginName}"/>
+	                </map:transform>
+	                <map:transform src="pages/presentation.xsl"/>
+	                <map:transform type="i18n">
+	                    <map:parameter name="locale" value="{locale:locale}"/>
+	                    <map:parameter name="default-catalogue-id" value="plugin.{request-attr:pluginName}"/>
+	                </map:transform>
+            		<map:serialize type="xhtml"/>
+            	</map:act>
+			</map:match>
+			
+			<map:match pattern="org.ametys.plugins.ugc.Content.simpleContent.*">
+                <map:redirect-to uri="cocoon://_plugins/web/content-type.simpleContent.{1}?pluginName={request-attr:pluginName}"/>
+            </map:match>
+			
+        </map:pipeline>
+	</map:pipelines>
+</map:sitemap>
Index: webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/actions/AddUGCAction.java
===================================================================
--- webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/actions/AddUGCAction.java	(revision 0)
+++ webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/actions/AddUGCAction.java	(revision 0)
@@ -0,0 +1,349 @@
+/*
+ *  Copyright 2010 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.ametys.plugins.ugc.actions;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
+import org.ametys.cms.repository.Content;
+import org.ametys.cms.repository.ModifiableContent;
+import org.ametys.cms.workflow.AbstractContentWorkflowComponent;
+import org.ametys.plugins.repository.AmetysObjectResolver;
+import org.ametys.plugins.repository.metadata.ModifiableCompositeMetadata;
+import org.ametys.plugins.repository.metadata.ModifiableRichText;
+import org.ametys.plugins.workflow.Workflow;
+import org.ametys.runtime.plugins.core.mail.SendMailHelper;
+import org.ametys.runtime.plugins.core.right.profile.Profile;
+import org.ametys.runtime.plugins.core.right.profile.ProfileBasedRightsManager;
+import org.ametys.runtime.right.RightsManager;
+import org.ametys.runtime.user.CurrentUserProvider;
+import org.ametys.runtime.user.UsersManager;
+import org.ametys.runtime.util.I18nUtils;
+import org.ametys.runtime.util.I18nizableText;
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.thread.ThreadSafe;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.acting.ServiceableAction;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Redirector;
+import org.apache.cocoon.environment.Request;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.commons.lang.StringUtils;
+
+import com.opensymphony.workflow.WorkflowException;
+
+/**
+ * Sends the comment for a given post
+ */
+public class AddUGCAction extends ServiceableAction implements ThreadSafe
+{
+    public static final String METADATA_LOGIN = "login";
+    /** The request parameter name for content id */
+    public static final String PARAMETER_CONTENTID = "contentId";
+    /** The request parameter name for author name */
+    public static final String PARAMETER_AUTHOR_NAME = "authorName";
+    /** The request parameter name for author email */
+    public static final String PARAMETER_AUTHOR_EMAIL = "authorEmail";
+    /** The request parameter name for author comment */
+    public static final String PARAMETER_AUTHOR_COMMENT = "authorComment";
+    /** The request parameter name for content */
+    public static final String PARAMETER_CONTENT = "content";
+    /** The request parameter name for title */
+    public static final String PARAMETER_TITLE = "title";
+    /** The request parameter key for captcha */
+    public static final String PARAMETER_CAPTCHA_KEY = "captcha-key";
+    /** The request parameter name for captcha */
+    public static final String PARAMETER_CAPTCHA_VALUE = "captcha-value";
+    
+    private static final String __UGC_PROFILE_NAME = "UGC_PROFILE";
+    
+    private static final String PLUGIN_CAT = "plugin.ugc";
+
+    /** The {@link AmetysObjectResolver} */
+    protected AmetysObjectResolver _resolver;
+
+    /** The users Manager */
+    protected UsersManager _usersManager;
+    
+    /** The listeners for this action */
+    protected UGCListenerExtensionPoint _ugcListeners;
+
+    protected I18nUtils _i18nUtils;
+    
+    protected ContentTypeExtensionPoint _cTypeEP;
+    private CurrentUserProvider _userProvider;
+    private Workflow _workflow;
+    private RightsManager _rightsManager;
+
+    @Override
+    public void service(ServiceManager smanager) throws ServiceException
+    {
+        super.service(smanager);
+
+        _userProvider = (CurrentUserProvider) smanager.lookup(CurrentUserProvider.ROLE);
+        _workflow = (Workflow) smanager.lookup(Workflow.ROLE);
+        _rightsManager = (RightsManager) smanager.lookup(RightsManager.ROLE);
+        _cTypeEP = (ContentTypeExtensionPoint) smanager.lookup(ContentTypeExtensionPoint.ROLE);
+        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
+        _usersManager = (UsersManager) manager.lookup(UsersManager.ROLE);
+        _ugcListeners = (UGCListenerExtensionPoint) manager.lookup(UGCListenerExtensionPoint.ROLE);
+        _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE);
+
+    }
+    
+    @Override
+    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
+    {
+        Request request = ObjectModelHelper.getRequest(objectModel);
+        Map<String, String> results = new HashMap<String, String>();
+        List<String> errors = _ugcListeners.addValidityCheck(objectModel);
+        if (errors.isEmpty())
+        {  
+            String contentId = null;
+            String authorName = request.getParameter(PARAMETER_AUTHOR_NAME);
+            String authorMail = request.getParameter(PARAMETER_AUTHOR_EMAIL);
+            String authorComment = request.getParameter(PARAMETER_AUTHOR_COMMENT);
+            String contentText = request.getParameter(PARAMETER_CONTENT);
+
+            if (!StringUtils.isBlank(request.getParameter(PARAMETER_CONTENT)))
+            {
+                contentId = initializeWorkflow(objectModel, parameters);
+                addContent(contentId, contentText);
+            }
+            else
+            {
+                contentId = request.getParameter(PARAMETER_CONTENTID);
+            }
+            addAuthorInformations(contentId, authorName, authorMail, authorComment);
+            sendMails(objectModel, contentId);
+            _ugcListeners.addSuccess(results);
+        }
+        else
+        {
+            _ugcListeners.addFailure(results, errors);
+        }
+        results.put("redirect", request.getHeader("Referer"));
+        
+        return results;
+    }
+    /**
+     * Add a textual content to a given content
+     * @param contentId
+     * @param contentText
+     * @throws Exception
+     */
+    private void addContent(String contentId, String contentText) throws Exception
+    {
+        Content content = _resolver.resolveById(contentId);
+        ModifiableContent modifiableContent = (ModifiableContent) content;
+        ModifiableCompositeMetadata meta = modifiableContent.getMetadataHolder();
+        ModifiableRichText richText = meta.getRichText("content", true);
+        richText.setMimeType("text/xml");
+        richText.setEncoding("UTF-8");
+        richText.setLastModified(new Date());
+        richText.setInputStream(new ByteArrayInputStream(("<?xml version='1.0' encoding='UTF-8'?><document><para>" + contentText + "</para></document>").getBytes("UTF-8")));
+        modifiableContent.saveChanges();
+    }
+
+    /**
+     * Add the authors mail, name and comment on the metadata of a given content
+     * @param contentId
+     * @param authorName
+     * @param authorMail
+     * @param authorComment
+     * @throws Exception
+     */
+    private void addAuthorInformations(String contentId, String authorName, String authorMail, String authorComment) throws Exception
+    {
+        Content content = _resolver.resolveById(contentId);
+        ModifiableContent modifiableContent = (ModifiableContent) content;
+        ModifiableCompositeMetadata meta = modifiableContent.getMetadataHolder();
+        meta.setMetadata("comment", authorComment);
+        ModifiableCompositeMetadata metaContact = meta.getCompositeMetadata("contact", true);
+        metaContact.setMetadata("name", authorName);
+        metaContact.setMetadata("mail", authorMail);
+        modifiableContent.saveChanges();
+    }
+    
+    /**
+     * Initialiaze a new workflow and return his id
+     * @return the created content id
+     */
+    protected String initializeWorkflow(Map objectModel, Parameters parameters) throws Exception
+    {
+        // Define all parameters and variables required to create the new content
+        Request request = ObjectModelHelper.getRequest(objectModel);
+        String ugcName = request.getParameter("ugcName");
+        String siteName = request.getParameter("siteName");
+        String title = request.getParameter(PARAMETER_TITLE);
+        String login = _userProvider.getUser();
+        
+        String workflowName = "content"; // hardcode ?
+        int actionId = 1; // hardcode ?
+
+        String lang = parameters.getParameter("lang");
+
+        String contentName = ugcName + " " + login;
+
+        
+        Content content;
+        try
+        {
+            // Create the person content.
+            Map<String, Object> params = new HashMap<String, Object>();
+            
+            // Workflow result
+            Map<String, Object> workflowResult = new HashMap<String, Object>();
+            params.put(AbstractContentWorkflowComponent.RESULT_MAP_KEY, workflowResult);
+            
+            // Workflow parameters.
+            params.put("workflowName", workflowName);
+            params.put("org.ametys.web.repository.site.Site", siteName);
+            params.put("org.ametys.cms.workflow.CreateContentFunction$contentName", contentName);
+            params.put("org.ametys.cms.workflow.CreateContentFunction$contentTitle", title);
+            params.put("org.ametys.cms.workflow.CreateContentFunction$contentType", "org.ametys.plugins.ugc.Content.simpleContent");
+            params.put("org.ametys.cms.workflow.CreateContentFunction$contentLanguage", lang);
+            _workflow.initialize(workflowName, actionId, params);
+            String contentId = (String) workflowResult.get("contentId");
+            content = _resolver.resolveById(contentId);
+            ModifiableContent modifiableContent = (ModifiableContent) content;
+            
+            modifiableContent.getMetadataHolder().setMetadata(METADATA_LOGIN, login);
+            modifiableContent.setTitle(title);
+            modifiableContent.saveChanges();
+
+            // Grant all the rights on the content to the content's user
+            if (_rightsManager instanceof ProfileBasedRightsManager)
+            {
+                ProfileBasedRightsManager profileBasedRM = (ProfileBasedRightsManager) _rightsManager;
+                Profile profile = getProfile(__UGC_PROFILE_NAME);
+
+                if (profile == null)
+                {
+                    // Create profile and give the user the rights to edit the created content
+                    profileBasedRM.grantAllPrivileges(login, "/contents/" + content.getName(), __UGC_PROFILE_NAME);
+                }
+                else
+                {
+                    profileBasedRM.addUserRight(login, "/contents/" + content.getName(), profile.getId());
+                }
+            }
+
+            // Return result
+            return content.getId();
+        }
+        catch (WorkflowException e)
+        {
+            getLogger().error("Error creating person content", e);
+            throw new ProcessingException("Error creating person content", e);
+        }
+    }
+    
+    /**
+     * Determines if the profile already exists
+     * @param profileName the profile name
+     * @return true if the profile already exists
+     */
+    protected Profile getProfile(String profileName)
+    {
+        for (Profile profile : ((ProfileBasedRightsManager) _rightsManager).getProfiles())
+        {
+            if (profileName.equals(profile.getName()))
+            {
+                return profile;
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * Send a mail to the contributor to notify the new content, and a mail to the author to confirm his suggestion.
+     * @param objectModel
+     * @param contentId
+     * @throws Exception
+     */
+    protected void sendMails(Map objectModel, String contentId) throws Exception
+    {
+        Request request = ObjectModelHelper.getRequest(objectModel);
+        String authorComment = request.getParameter("authorComment");
+        String authorName = request.getParameter("authorName");
+        String authorEmail = request.getParameter("authorEmail");
+        String mailNotification = request.getParameter("mailNotification");
+        String ugcName = request.getParameter("ugcName");
+        String siteName = request.getParameter("siteName");
+        Content content = _resolver.resolveById(contentId);
+        String title = content.getTitle();
+        String sender = "sender@ametys.org";
+
+        String bodyMailForContrib;
+        String bodyMailForAuthor;
+        String subjectMailForContrib;
+        String subjectMailForAuthor;
+         
+        // build body mail for contrib
+        List<String> bodyMailForContribParam = new ArrayList<String>();
+        bodyMailForContribParam.add(authorName);
+        bodyMailForContribParam.add(title);
+        bodyMailForContribParam.add(ugcName);
+        bodyMailForContribParam.add(siteName);
+        bodyMailForContribParam.add(authorComment);
+        bodyMailForContribParam.add(authorEmail);
+        I18nizableText i18nBodyMailForContrib = new I18nizableText(PLUGIN_CAT, "PLUGINS_UGC_MAIL_BODY_CONTRIB_NEW_CONTENT", bodyMailForContribParam);
+        bodyMailForContrib = _i18nUtils.translate(i18nBodyMailForContrib);
+         
+        // build body mail for author
+        List<String> bodyMailForAuthorParam = new ArrayList<String>();
+        bodyMailForAuthorParam.add(authorName);
+        bodyMailForAuthorParam.add(title);
+        bodyMailForAuthorParam.add(siteName);
+        I18nizableText i18nBodyMailForAuthor = new I18nizableText(PLUGIN_CAT, "PLUGINS_UGC_MAIL_BODY_AUTHOR_NEW_CONTENT", bodyMailForAuthorParam);
+        bodyMailForAuthor = _i18nUtils.translate(i18nBodyMailForAuthor);
+
+        // build subject mail for contrib
+        List<String> subjectMailForContribParam = new ArrayList<String>();
+        subjectMailForContribParam.add(ugcName);
+        subjectMailForContribParam.add(authorName);
+        I18nizableText i18nSubjectMailForContrib = new I18nizableText(PLUGIN_CAT, "PLUGINS_UGC_MAIL_SUBJECT_CONTRIB_NEW_CONTENT", subjectMailForContribParam);
+        subjectMailForContrib = _i18nUtils.translate(i18nSubjectMailForContrib);
+         
+        // build subject mail for author
+        List<String> subjectMailForAuthorParam = new ArrayList<String>();
+        subjectMailForAuthorParam.add(siteName);
+        I18nizableText i18nSubjectMailForAuthor = new I18nizableText(PLUGIN_CAT, "PLUGINS_UGC_MAIL_SUBJECT_AUTHOR_NEW_CONTENT", subjectMailForAuthorParam);
+        subjectMailForAuthor = _i18nUtils.translate(i18nSubjectMailForAuthor);
+         
+        // send mail to contrib
+        SendMailHelper.sendMail(subjectMailForContrib, null, bodyMailForContrib, mailNotification, sender);
+
+        // send mail to author
+        SendMailHelper.sendMail(subjectMailForAuthor, null, bodyMailForAuthor, authorEmail, sender);
+    }
+    
+    protected void sendMails(Map objectModel) throws Exception{
+        Request request = ObjectModelHelper.getRequest(objectModel);
+        String contentId = request.getParameter("contentId");
+        sendMails(objectModel, contentId);
+    }
+    
+}
Index: webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/actions/DefaultUGCListener.java
===================================================================
--- webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/actions/DefaultUGCListener.java	(revision 0)
+++ webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/actions/DefaultUGCListener.java	(revision 0)
@@ -0,0 +1,167 @@
+/*
+ *  Copyright 2010 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.ametys.plugins.ugc.actions;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.ametys.cms.captcha.CaptchaHelper;
+import org.ametys.cms.observation.ObservationManager;
+import org.ametys.cms.repository.Content;
+import org.ametys.plugins.repository.AmetysObjectResolver;
+import org.ametys.plugins.repository.metadata.CompositeMetadata;
+import org.ametys.plugins.repository.metadata.RichText;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Default impl to handle every default behavior
+ */
+public class DefaultUGCListener implements UGCListener, Serviceable
+{
+    /** The pattern to check emails */
+    protected static final Pattern EMAIL_VALIDATOR = Pattern.compile("^([a-z0-9._-]+@[a-z0-9.-]{2,}[.][a-z]{2,3})$");
+    /** The pattern to check url */
+    protected static final Pattern URL_VALIDATOR = Pattern.compile("^(https?:\\/\\/.+)?$");
+    /** The {@link AmetysObjectResolver} */
+    protected AmetysObjectResolver _resolver;
+    
+    /** Observer manager. */
+    protected ObservationManager _observerManager;
+
+    @Override
+    public void service(ServiceManager manager) throws ServiceException
+    {
+        _observerManager = (ObservationManager) manager.lookup(ObservationManager.ROLE);
+        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
+    }
+    
+    @Override
+    public void addFailure(Map<String, String> results, List<String> errors)
+    {
+        String errorsS = results.get("errors");
+        if (errorsS == null)
+        {
+            errorsS = StringUtils.join(errors, ";");
+        }
+        else
+        {
+            errorsS += ";" + StringUtils.join(errors, ";");
+        }
+        results.put("errors", errorsS);
+    }
+
+    @Override
+    public void addSuccess(Map<String, String> results)
+    {
+
+    }
+
+    @Override
+    public List<String> addValidityCheck(Map objectModel)
+    {
+        Request request = ObjectModelHelper.getRequest(objectModel);
+
+        List<String> errors = new ArrayList<String>();
+
+        if (StringUtils.isBlank(request.getParameter(AddUGCAction.PARAMETER_AUTHOR_NAME)))
+        {
+            errors.add("plugin.ugc:PLUGINS_UGC_SUBMIT_ERROR_NAME");
+        }
+        
+        if (!EMAIL_VALIDATOR.matcher(StringUtils.trimToEmpty(request.getParameter(AddUGCAction.PARAMETER_AUTHOR_EMAIL))).matches())
+        {
+            errors.add("plugin.ugc:PLUGINS_UGC_SUBMIT_ERROR_EMAIL");
+        }
+        
+        if (StringUtils.isBlank(request.getParameter(AddUGCAction.PARAMETER_TITLE)))
+        {
+            errors.add("plugin.ugc:PLUGINS_UGC_SUBMIT_ERROR_TITLE");
+        }
+       
+        // The request must have a textual content or a contentId (depends if JS is activated or not)
+        if (StringUtils.isBlank(request.getParameter(AddUGCAction.PARAMETER_CONTENT)))
+        {
+            String contentId = request.getParameter(AddUGCAction.PARAMETER_CONTENTID);
+            if (StringUtils.isBlank(contentId))
+            {
+                errors.add("plugin.ugc:PLUGINS_UGC_SUBMIT_ERROR_CONTENT");
+            }
+            else
+            {
+                Content content = _resolver.resolveById(contentId);
+                CompositeMetadata meta = content.getMetadataHolder();
+                if (isContentEmpty(meta))
+                {
+                    // errors.add("plugin.ugc:PLUGINS_UGC_SUBMIT_ERROR_CONTENT_INVALID");
+                	// bug on isContentEmpty(meta) in the regexpr
+                }
+            }
+        }
+
+        String captchaKey = request.getParameter(AddUGCAction.PARAMETER_CAPTCHA_KEY);
+        String captchaValue = request.getParameter(AddUGCAction.PARAMETER_CAPTCHA_VALUE);
+        if (StringUtils.isBlank(captchaKey) || StringUtils.isBlank(captchaValue))
+        {
+            errors.add("plugin.ugc:PLUGINS_UGC_SUBMIT_ERROR_CAPTCHA");
+        }
+        else 
+        {
+            if (!CaptchaHelper.checkAndInvalidate(captchaKey, captchaValue)) 
+            {
+                errors.add("plugin.ugc:PLUGINS_UGC_SUBMIT_ERROR_CAPTCHA");
+            }
+        }
+        return errors;
+    }
+    
+    private boolean isContentEmpty(CompositeMetadata metadata)
+    {
+        if (!metadata.hasMetadata("content"))
+        {
+            return true;
+        }
+        RichText richText = metadata.getRichText("content");
+        if (richText.getLength() <= 0)
+        {
+            return true;
+        }
+        try
+        {
+            // check if the richText "content" have at least one alphanumeric character
+            Configuration configuration = new DefaultConfigurationBuilder().build(richText.getInputStream());
+            String value = configuration.getChild("para").getValue();
+            if (!value.matches("^.*\\w.*$")) // FIXME check if there is on word character in the content 
+            {
+                return true;
+            }
+        }
+        catch (Exception e)
+        {
+            return true;
+        }
+        return false;
+    }
+}
Index: webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/actions/UGCListener.java
===================================================================
--- webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/actions/UGCListener.java	(revision 0)
+++ webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/actions/UGCListener.java	(revision 0)
@@ -0,0 +1,49 @@
+/*
+ *  Copyright 2010 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.ametys.plugins.ugc.actions;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.avalon.framework.component.Component;
+
+/**
+ * A listener call on add comment action
+ */
+public interface UGCListener extends Component
+{
+    /**
+     * Comment added successfuly
+     * @param results The action result map
+     * @param comment The new comment
+     */
+    public void addSuccess(Map<String, String> results);
+    
+    /**
+     * Comment not added
+     * @param results The action result map
+     * @param errors The errors encountered
+     */
+    public void addFailure(Map<String, String> results, List<String> errors);
+    
+    /**
+     * Checks the sent parameters for errors
+     * @param objectModel The cocoon object model
+     * @return An list of error messages (empty if no errors)
+     */
+    public List<String> addValidityCheck(Map objectModel);
+}
Index: webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/actions/UGCListenerExtensionPoint.java
===================================================================
--- webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/actions/UGCListenerExtensionPoint.java	(revision 0)
+++ webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/actions/UGCListenerExtensionPoint.java	(revision 0)
@@ -0,0 +1,81 @@
+/*
+ *  Copyright 2010 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.ametys.plugins.ugc.actions;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.ametys.runtime.plugin.component.AbstractThreadSafeComponentExtensionPoint;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+
+/**
+ * Handle all the listeners for the add comment action
+ */
+public class UGCListenerExtensionPoint extends AbstractThreadSafeComponentExtensionPoint<UGCListener>
+{
+    /** The avalon role */
+    public static final String ROLE = UGCListenerExtensionPoint.class.getName();
+    
+    /**
+     * Call success method on all listeners 
+     * @param results
+     * @param comment
+     */
+    public void addSuccess(Map<String, String> results)
+    {
+        for (String listenerId : getExtensionsIds())
+        {
+            UGCListener listener = getExtension(listenerId);
+            listener.addSuccess(results);
+        }
+    }
+
+
+    /**
+     * Call failure method on all listeners 
+     * @param results The action result map
+     * @param errors The errors encountered
+     */
+    public void addFailure(Map<String, String> results, List<String> errors)
+    {
+        for (String listenerId : getExtensionsIds())
+        {
+            UGCListener listener = getExtension(listenerId);
+            listener.addFailure(results, errors);
+        }
+    }
+    
+    /**
+     * Call the validityCheck method on all listeners and add the results
+     * @param content The content to comment
+     * @param objectModel The cocoon object model
+     * @return An list of error messages (empty if no errors)
+     */
+    public List<String> addValidityCheck(Map objectModel)
+    {
+        List<String> errors = new ArrayList<String>();
+        for (String listenerId : getExtensionsIds())
+        {
+            UGCListener listener = getExtension(listenerId);
+            errors.addAll(listener.addValidityCheck(objectModel));
+        }
+        
+        return errors;
+    }
+}
Index: webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/init/InitializeUGCWorkflowAction.java
===================================================================
--- webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/init/InitializeUGCWorkflowAction.java	(revision 0)
+++ webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/init/InitializeUGCWorkflowAction.java	(revision 0)
@@ -0,0 +1,160 @@
+/*
+ *  Copyright 2010 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.ametys.plugins.ugc.init;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
+import org.ametys.cms.observation.AbstractNotifierAction;
+import org.ametys.cms.repository.Content;
+import org.ametys.cms.repository.ModifiableContent;
+import org.ametys.cms.workflow.AbstractContentWorkflowComponent;
+import org.ametys.plugins.workflow.Workflow;
+import org.ametys.runtime.plugins.core.right.profile.Profile;
+import org.ametys.runtime.plugins.core.right.profile.ProfileBasedRightsManager;
+import org.ametys.runtime.right.RightsManager;
+import org.ametys.runtime.user.CurrentUserProvider;
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Redirector;
+import org.apache.cocoon.environment.Request;
+import org.apache.cocoon.environment.SourceResolver;
+
+import com.opensymphony.workflow.WorkflowException;
+
+/**
+ * Creates the person content.
+ */
+public class InitializeUGCWorkflowAction extends AbstractNotifierAction
+{
+    public static final String METADATA_LOGIN = "login";
+    
+    private static final String __UGC_PROFILE_NAME = "UGC_PROFILE";
+    
+    protected ContentTypeExtensionPoint _cTypeEP;
+    private CurrentUserProvider _userProvider;
+    private Workflow _workflow;
+    private RightsManager _rightsManager;
+    
+    @Override
+    public void service(ServiceManager smanager) throws ServiceException
+    {
+        super.service(smanager);
+        _userProvider = (CurrentUserProvider) smanager.lookup(CurrentUserProvider.ROLE);
+        _workflow = (Workflow) smanager.lookup(Workflow.ROLE);
+        _rightsManager = (RightsManager) smanager.lookup(RightsManager.ROLE);
+        _cTypeEP = (ContentTypeExtensionPoint) smanager.lookup(ContentTypeExtensionPoint.ROLE);
+    }
+    
+    @Override
+    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
+    {
+        // Define all parameters and variables required to create the new content
+        Request request = ObjectModelHelper.getRequest(objectModel);
+        String ugcName = request.getParameter("ugcName");
+        String siteName = request.getParameter("siteName");
+        
+        String login = _userProvider.getUser();
+        
+        String workflowName = "content"; // hardcode ?
+        int actionId = 1; // hardcode ?
+
+        String lang = parameters.getParameter("lang");
+
+        String contentName = ugcName + " " + login;
+        String title = contentName;
+        
+        Content content;
+        try
+        {
+            // Create the person content.
+            Map<String, Object> params = new HashMap<String, Object>();
+            
+            // Workflow result
+            Map<String, Object> workflowResult = new HashMap<String, Object>();
+            params.put(AbstractContentWorkflowComponent.RESULT_MAP_KEY, workflowResult);
+            
+            // Workflow parameters.
+            params.put("workflowName", workflowName);
+            params.put("org.ametys.web.repository.site.Site", siteName);
+            params.put("org.ametys.cms.workflow.CreateContentFunction$contentName", contentName);
+            params.put("org.ametys.cms.workflow.CreateContentFunction$contentTitle", title);
+            params.put("org.ametys.cms.workflow.CreateContentFunction$contentType", "org.ametys.plugins.ugc.Content.simpleContent");
+            params.put("org.ametys.cms.workflow.CreateContentFunction$contentLanguage", lang);
+            _workflow.initialize(workflowName, actionId, params);
+            String contentId = (String) workflowResult.get("contentId");
+            content = _resolver.resolveById(contentId);
+            
+            // FIXME API Check if modifiable.
+            ModifiableContent modifiableContent = (ModifiableContent) content;
+            
+            modifiableContent.getMetadataHolder().setMetadata(METADATA_LOGIN, login);
+            modifiableContent.setTitle(title);
+            modifiableContent.saveChanges();
+
+            // Grant all the rights on the content to the content's user
+            if (_rightsManager instanceof ProfileBasedRightsManager)
+            {
+                ProfileBasedRightsManager profileBasedRM = (ProfileBasedRightsManager) _rightsManager;
+                Profile profile = getProfile(__UGC_PROFILE_NAME);
+                
+                if (profile == null)
+                {
+                    // Create profile and give the user the rights to edit the created content
+                    profileBasedRM.grantAllPrivileges(login, "/contents/" + content.getName(), __UGC_PROFILE_NAME);
+                }
+                else
+                {
+                    profileBasedRM.addUserRight(login, "/contents/" + content.getName(), profile.getId());
+                }
+            }
+            
+            // Return result
+            Map<String, String> result = new HashMap<String, String>();
+            result.put("contentId", content.getId());
+            
+            return result;
+        }
+        catch (WorkflowException e)
+        {
+            getLogger().error("Error creating person content", e);
+            throw new ProcessingException("Error creating person content", e);
+        }
+    }
+    
+    /**
+     * Determines if the profile already exists
+     * @param profileName the profile name
+     * @return true if the profile already exists
+     */
+    protected Profile getProfile(String profileName)
+    {
+        for (Profile profile : ((ProfileBasedRightsManager) _rightsManager).getProfiles())
+        {
+            if (profileName.equals(profile.getName()))
+            {
+                return profile;
+            }
+        }
+        return null;
+    }
+    
+}
Index: webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/preview/GetUGCPreviewTransformer.java
===================================================================
--- webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/preview/GetUGCPreviewTransformer.java	(revision 0)
+++ webapp/cms/plugins/ugc/src/org/ametys/plugins/ugc/preview/GetUGCPreviewTransformer.java	(revision 0)
@@ -0,0 +1,104 @@
+package org.ametys.plugins.ugc.preview;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.transformation.AbstractTransformer;
+import org.apache.commons.lang.StringUtils;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+
+// copy of org.ametys.plugins.blog.posts.AbbreviateTransformer
+
+public class GetUGCPreviewTransformer extends AbstractTransformer
+{
+    
+    /** The max character count. */
+    protected int _maxCharCount;
+    
+    /** The ellipsis. */
+    protected String _ellipsis;
+    
+    /** The current character count. */
+    protected int _charCount;
+    
+    /** The maximum depth attained. */
+    protected int _maxDepth;
+    
+    /** The current depth. */
+    protected int _currentDepth;
+    
+    @Override
+    public void setup(SourceResolver resolver, Map objectModel, String src, Parameters parameters) throws ProcessingException, SAXException, IOException
+    {
+        _maxCharCount = parameters.getParameterAsInteger("max-characters", 200);
+        _ellipsis = parameters.getParameter("ellipsis", "...");
+    }
+    
+    @Override
+    public void startDocument() throws SAXException
+    {
+        _charCount = 0;
+        _currentDepth = 0;
+        _maxDepth = 0;
+        
+        super.startDocument();
+    }
+    
+    @Override
+    public void startElement(String uri, String loc, String raw, Attributes a) throws SAXException
+    {
+        _currentDepth++;
+        
+        if (_charCount < _maxCharCount)
+        {
+            super.startElement(uri, loc, raw, a);
+        }
+    }
+    
+    @Override
+    public void endElement(String uri, String loc, String raw) throws SAXException
+    {
+        if (_charCount < _maxCharCount)
+        {
+            super.endElement(uri, loc, raw);
+        }
+        else if (_currentDepth <= _maxDepth)
+        {
+            super.endElement(uri, loc, raw);
+            _maxDepth--;
+        }
+        
+        _currentDepth--;
+    }
+    
+    @Override
+    public void characters(char[] c, int start, int len) throws SAXException
+    {
+        String text = new String(c, start, len).trim();
+        int length = text.length();
+        
+        if (_charCount < _maxCharCount)
+        {
+            if ((_charCount + length) <= _maxCharCount)
+            {
+                super.characters(c, start, len);
+            }
+            else
+            {
+                _maxDepth = _currentDepth;
+                super.characters(text.toCharArray(), 0, _maxCharCount - _charCount);
+                super.characters(_ellipsis.toCharArray(), 0, _ellipsis.length());
+            }
+            
+            if (StringUtils.isNotBlank(text))
+            {
+                _charCount += length;
+            }
+        }
+    }
+}
Index: webapp/cms/plugins/ugc/stylesheets/content/common.xsl
===================================================================
--- webapp/cms/plugins/ugc/stylesheets/content/common.xsl	(revision 0)
+++ webapp/cms/plugins/ugc/stylesheets/content/common.xsl	(revision 0)
@@ -0,0 +1,317 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2010 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
+                              xmlns:docbook="http://docbook.org/ns/docbook" 
+                              xmlns:i18n="http://apache.org/cocoon/i18n/2.1" 
+                              xmlns:cms="http://ametys.org/cms/3.0"
+                              xmlns:resolver="org.ametys.cms.transformation.xslt.ResolveURIComponent"
+						      xmlns:ametys="org.ametys.web.transformation.xslt.AmetysXSLTHelper"
+                              extension-element-prefixes="cms" 
+                              exclude-result-prefixes="docbook resolver ametys">
+    
+    <xsl:import href="docbookenhancement://docbook2html.xsl"/>    
+    <xsl:import href="service:web://stylesheets/utils.xsl"/>        
+    <xsl:import href="plugin:core://stylesheets/helper/text.xsl"/>
+    <xsl:import href="plugin:cms://pages/comments/helper/comments_3.3.xsl"/>    
+    <xsl:import href="plugin:cms://stylesheets/helper/common_3.3.xsl"/>    
+    
+    <!-- The CSS classname that will be set on the surrounding DIV element -->
+    <xsl:variable name="common-content-css-class-name" />
+    <!-- The name of content -->
+    <xsl:variable name="common-content-name" />
+
+    <!-- +
+         | STRUCTURE
+         + -->
+
+    <!-- The common template to call to build your service structure -->   
+    <xsl:template match="content">
+        <html>
+            <head>
+                <xsl:call-template name="common-content-head"/>        
+            </head>
+            <body id="default"> 
+                <xsl:call-template name="common-content-body"/>
+            </body>
+        </html>   
+   </xsl:template>
+
+    <!-- +
+         | HEAD
+         + -->
+   
+   <!-- The template called in the HEAD tag. -->
+   <xsl:template name="common-content-head">
+        <xsl:call-template name="common-content-head-title"/>
+        <xsl:call-template name="common-content-head-css"/>
+        <xsl:call-template name="common-content-head-js"/>
+        <xsl:call-template name="common-content-head-other"/>
+        <xsl:call-template name="common-content-metadata-dublin-core"/>
+        <xsl:call-template name="common-content-metadata-other"/> 
+   </xsl:template>
+
+   <!-- Override this template to add specific title -->
+   <xsl:template name="common-content-head-title"/>   
+   
+   <!-- Override this template to add stuff in the head (but JS or CSS) -->
+   <xsl:template name="common-content-head-other"/>
+
+   <!-- Override this template to add CSS -->
+   <xsl:template name="common-content-head-css"/>
+   
+   <!-- Override this template to add JS -->
+   <xsl:template name="common-content-head-js"/> 
+   
+   <!-- Template used by content for balise title -->
+   <xsl:template name="common-content-head-title-content">
+   		<xsl:param name="title" select="metadata/title"/>
+   
+        <title><xsl:value-of select="$title"/></title>
+   </xsl:template>    
+   
+    <!-- +
+         | METADATA
+         + -->   
+
+    <!-- Dublin core metadata -->
+    <xsl:template name="common-content-metadata-dublin-core">
+        <xsl:if test="dublin-core-metadata/node()[name() = 'subject' and normalize-space(.) != '']">
+            <meta name="DC.subject">
+                <xsl:attribute name="content"> 
+                     <xsl:for-each select="dublin-core-metadata/node()[name() = 'subject' and normalize-space(.) != '']">
+                        <xsl:value-of select="."/><xsl:if test="not(position()=last())"><xsl:text>, </xsl:text></xsl:if>
+                     </xsl:for-each>
+                </xsl:attribute>
+            </meta>
+        </xsl:if>
+        
+        <xsl:for-each select="dublin-core-metadata/node()[name() != 'subject' and normalize-space(.) != '']">
+            <meta name="DC.{name()}" content="{.}"/>
+        </xsl:for-each>
+                
+        <!-- Dublin Core -->
+        <link rel="meta" href="{$contextPath}/plugins/cms/dublincore/content.rdf?contentId={@id}" />    
+    </xsl:template>  
+
+    <!-- Other metadata -->
+    <xsl:template name="common-content-metadata-other">
+        <!-- Last modifiedDate -->
+        <xsl:if test="@lastModifiedAt">
+            <meta name="lastModificationRaw" content="{@lastModifiedAt}" />    
+        </xsl:if>
+    </xsl:template>   
+   
+   <!-- +
+         | BODY
+         + -->
+    <!-- The content HTML structure -->
+    <xsl:template name="common-content-body">
+        <div class="ametys-cms-content {$common-content-css-class-name} wrapper">
+            <xsl:call-template name="common-content-body-title"/>
+            
+            <xsl:call-template name="common-content-body-content"/>
+        </div>            
+    </xsl:template>
+   
+   
+   <!-- +
+         | BODY ELEMENTS
+         + -->
+    <!-- Vue main -->
+    <xsl:template name="common-content-body-title-content">
+        <xsl:param name="title" select="metadata/title"/>
+        <xsl:param name="subtitle" select="metadata/document-subtitle"/>
+        
+        <h1>
+        	<span class="content-title"><xsl:value-of select="$title"/></span>
+            <xsl:if test="$subtitle != ''">
+                <span class="content-subtitle"><xsl:value-of select="$subtitle"/></span>
+            </xsl:if>
+        </h1>
+    </xsl:template>
+    
+    <!-- Illustration big size -->
+    <xsl:template name="common-content-body-image-bigsize">
+        <xsl:param name="image" select="metadata/illustration/image"/>
+        <xsl:param name="alternative" select="metadata/illustration/alt-text"/>
+        <xsl:param name="maxWidth" select="'150'"/>
+        <xsl:param name="maxHeight" select="'150'"/>
+        <xsl:param name="class" select="'big'"/>
+        
+        <xsl:call-template name="common-content-body-image">
+            <xsl:with-param name="image" select="$image"/>
+            <xsl:with-param name="alternative" select="$alternative"/>
+            <xsl:with-param name="maxWidth" select="$maxWidth"/>
+            <xsl:with-param name="maxHeight" select="$maxHeight"/>
+            <xsl:with-param name="class" select="$class"/>
+        </xsl:call-template>
+    </xsl:template>
+    
+    <!-- Illustration small size -->
+    <xsl:template name="common-content-body-image-smallsize">
+        <xsl:param name="image" select="metadata/illustration/image"/>
+        <xsl:param name="alternative" select="metadata/illustration/alt-text"/>
+        <xsl:param name="maxWidth" select="'100'"/>
+        <xsl:param name="maxHeight" select="'100'"/>
+        <xsl:param name="class" select="'small'"/>
+        
+        <xsl:call-template name="common-content-body-image">
+            <xsl:with-param name="image" select="$image"/>
+            <xsl:with-param name="alternative" select="$alternative"/>
+            <xsl:with-param name="maxWidth" select="$maxWidth"/>
+            <xsl:with-param name="maxHeight" select="$maxHeight"/>
+            <xsl:with-param name="class" select="$class"/>
+        </xsl:call-template>
+    </xsl:template>
+    
+    <!-- Template used to display the content illustration -->
+    <xsl:template name="common-content-body-image">
+        <xsl:param name="image"/>
+        <xsl:param name="alternative"/>
+        <xsl:param name="maxWidth"/>
+        <xsl:param name="maxHeight"/>
+        <xsl:param name="class"/>
+        
+        <xsl:if test="$image">
+            <div class="content-illustration {$class}">
+                <img src="{resolver:resolveBoundedImage($image/@type, $image/@path, $maxWidth, $maxHeight)}" alt="{$alternative}"/>
+            </div>
+        </xsl:if>        
+    </xsl:template>  
+    
+    <!-- Template used for the rich content -->
+    <xsl:template name="common-content-body-content-rich">
+        <xsl:param name="level" select="0"/>
+        <xsl:param name="content" select="metadata/content"/>
+
+        <xsl:if test="cms:isNotRichTextEmpty($content)">
+	       	<xsl:variable name="raw-is-title-visible">
+			    <xsl:call-template name="common-content-body-title-content"/>
+			</xsl:variable>
+	        
+	        <xsl:variable name="truelevel">
+		    	<xsl:choose>
+		    		<xsl:when test="string-length($raw-is-title-visible) &gt; 0"><xsl:value-of select="2 + number($level)"/></xsl:when>
+		    		<xsl:otherwise><xsl:value-of select="1 + number($level)"/></xsl:otherwise>
+		    	</xsl:choose>
+			</xsl:variable>
+				    
+            <xsl:apply-templates select="$content/docbook:article">
+                <xsl:with-param name="level" select="$truelevel"/>
+            </xsl:apply-templates>
+        </xsl:if>    
+    </xsl:template>
+
+    <!-- Contact, Publish date... -->
+    <xsl:template name="common-content-body-meta">
+    	<xsl:if test="metadata/contact/name or metadata/contact/mail or @lastValidatedAt">
+    		<div class="meta">
+    			<xsl:call-template name="common-content-body-contact"/>
+		    	<xsl:call-template name="common-content-body-publish-date"/>
+	    	</div>
+    	</xsl:if>
+    </xsl:template>
+    
+    <!-- Template used to display the contact -->
+    <xsl:template name="common-content-body-contact">
+        <xsl:if test="metadata/contact/name or metadata/contact/mail">
+            <p class="content-contact">
+                <i18n:text i18n:key="CONTENT_FRONTOFFICE_CONTACT" i18n:catalogue="plugin.web"/>
+                <xsl:text> </xsl:text>
+                <xsl:if test="metadata/contact/name"><xsl:value-of select="metadata/contact/name"/></xsl:if>
+                <xsl:if test="metadata/contact/name and metadata/contact/mail"><xsl:text> (</xsl:text></xsl:if>
+                <xsl:if test="metadata/contact/mail">
+                    <xsl:call-template name="mail-antispam">
+                        <xsl:with-param name="mail" select="metadata/contact/mail"></xsl:with-param>
+                    </xsl:call-template>
+                </xsl:if>
+                <xsl:if test="metadata/contact/name and metadata/contact/mail"><xsl:text>)</xsl:text></xsl:if>
+            </p>
+        </xsl:if>    
+    </xsl:template>
+    
+    <xsl:template name="common-content-body-publish-date">
+        <xsl:if test="@lastValidatedAt">
+            <p class="content-published-date">
+                <i18n:text i18n:key="CONTENT_FRONTOFFICE_LASTPUBLICATIONDATE" i18n:catalogue="plugin.web"/>
+                <xsl:text> </xsl:text> 
+                <xsl:call-template name="common-utils-date-pattern">
+                    <xsl:with-param name="date" select="@lastValidatedAt"/>
+                </xsl:call-template>                
+            </p>          
+        </xsl:if>
+    </xsl:template>    
+    
+    <xsl:template name="common-content-body-comments">
+        <!-- Comments -->
+		<xsl:call-template name="comments"/>
+    </xsl:template>
+    <xsl:template name="comment-class">
+    	<xsl:call-template name="common-utils-class"/>
+	</xsl:template>
+	<xsl:template name="comment-form-showhint">
+        <p class="mandatory-hint">
+        	<i18n:text i18n:key="PLUGINS_WEB_FRONTOFICE_MANDATORY_LABEL" i18n:catalogue="plugin.web"/>
+        </p>
+	</xsl:template>	
+	<xsl:template name="comment-form-manadtorymarker">
+		<span class="mandatory-marker"><i18n:text i18n:key="PLUGINS_WEB_FRONTOFICE_MANDATORY_FIELD" i18n:catalogue="plugin.web"/></span>
+	</xsl:template>	
+
+    <!-- Abstract -->
+    <xsl:template name="common-content-body-simpletext">
+        <xsl:param name="css-class-name" />
+        <xsl:param name="text" />
+        <xsl:param name="defaultText" />
+        <xsl:param name="maxDefaultTextSize" />
+
+        <p>
+            <xsl:attribute name="class"><xsl:value-of select="$css-class-name"/></xsl:attribute>
+            <xsl:call-template name="common-utils-simpletext">
+                <xsl:with-param name="text" select="$text"/>                
+                <xsl:with-param name="defaultText" select="$defaultText"/>                
+                <xsl:with-param name="maxDefaultTextSize" select="$maxDefaultTextSize"/>                
+            </xsl:call-template>            
+        </p>
+    </xsl:template>
+    
+    <!-- Link read more -->
+    <xsl:template name="common-content-body-readmore">
+        <xsl:if test="//pages/page">        
+            <p class="content-read-more">
+                <a href="{resolver:resolve('page', //pages/page/@id, false)}"><i18n:text i18n:key="CONTENT_FRONTOFFICE_READMORE" i18n:catalogue="plugin.web"/></a>
+            </p>
+        </xsl:if>
+    </xsl:template> 
+    
+    <!-- Link used for the view link -->
+    <xsl:template name="common-content-body-link">
+        <xsl:param name="title" select="metadata/title"/>
+        
+        <p class="content-link">
+            <xsl:choose>
+                <xsl:when test="//pages/page">
+                    <a href="{resolver:resolve('page', //pages/page/@id, false)}"><xsl:value-of select="$title"/></a>
+                </xsl:when>
+                <xsl:otherwise>
+                    <xsl:value-of select="$title"/>
+                </xsl:otherwise>
+            </xsl:choose>
+        </p>    
+    </xsl:template>
+            
+</xsl:stylesheet>                              
\ No newline at end of file
Index: webapp/cms/plugins/ugc/stylesheets/content/simpleContent/simpleContent-abstract.xsl
===================================================================
--- webapp/cms/plugins/ugc/stylesheets/content/simpleContent/simpleContent-abstract.xsl	(revision 0)
+++ webapp/cms/plugins/ugc/stylesheets/content/simpleContent/simpleContent-abstract.xsl	(revision 0)
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2010 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+   
+<!-- Copy from plugins/web/stylesheets/content/article -->
+   
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                              xmlns:i18n="http://apache.org/cocoon/i18n/2.1"
+                              xmlns:docbook="http://docbook.org/ns/docbook"
+                              xmlns:text="http://ametys.org/text/3.0" 
+                              xmlns:resolver="org.ametys.cms.transformation.xslt.ResolveURIComponent"
+                              exclude-result-prefixes="docbook"
+                              extension-element-prefixes="text resolver">
+
+	<xsl:import href="article.xsl"/>
+	
+    <!-- Used in common.xsl -->
+    <xsl:variable name="common-content-css-class-name">article view-abstract</xsl:variable>     
+        
+        
+    <!-- +
+         | BODY
+         + -->
+    <!-- Used in common.xsl --> 
+    <xsl:template name="common-content-body-content">
+        <!-- Image -->
+        <xsl:call-template name="common-content-body-image-smallsize"/>    
+    
+        <!-- Abstract -->
+        <xsl:call-template name="common-content-body-simpletext">
+            <xsl:with-param name="css-class-name">content-abstract</xsl:with-param>
+            <xsl:with-param name="text" select="metadata/abstract" />
+            <xsl:with-param name="defaultText" select="metadata/content/docbook:article" />
+            <xsl:with-param name="maxDefaultTextSize" select="200" />
+        </xsl:call-template>
+        
+        <!-- Read more -->
+        <xsl:call-template name="common-content-body-readmore"/>
+        
+        <div class="content-richtext-end"><xsl:comment>empty</xsl:comment></div>
+    </xsl:template>    
+
+</xsl:stylesheet>
Index: webapp/cms/plugins/ugc/stylesheets/content/simpleContent/simpleContent-link.xsl
===================================================================
--- webapp/cms/plugins/ugc/stylesheets/content/simpleContent/simpleContent-link.xsl	(revision 0)
+++ webapp/cms/plugins/ugc/stylesheets/content/simpleContent/simpleContent-link.xsl	(revision 0)
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2010 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+   
+<!-- Copy from plugins/web/stylesheets/content/article -->
+   
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                              xmlns:i18n="http://apache.org/cocoon/i18n/2.1">
+
+	<xsl:import href="article.xsl"/>
+    
+    <!-- Used in common.xsl -->
+    <xsl:variable name="common-content-css-class-name">article view-link</xsl:variable>
+    
+    
+    <!-- +
+         | BODY
+         + -->
+    <!-- Empty title for link view--> 
+    <xsl:template name="common-content-body-title"/>
+        
+    <!-- Used in common.xsl -->
+    <xsl:template name="common-content-body-content">
+        <xsl:call-template name="common-content-body-link"/>
+    </xsl:template> 
+
+</xsl:stylesheet>
Index: webapp/cms/plugins/ugc/stylesheets/content/simpleContent/simpleContent-main.xsl
===================================================================
--- webapp/cms/plugins/ugc/stylesheets/content/simpleContent/simpleContent-main.xsl	(revision 0)
+++ webapp/cms/plugins/ugc/stylesheets/content/simpleContent/simpleContent-main.xsl	(revision 0)
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2010 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+   
+<!-- Copy from plugins/web/stylesheets/content/article -->
+   
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                              xmlns:i18n="http://apache.org/cocoon/i18n/2.1">
+
+	<xsl:import href="simpleContent.xsl"/>
+	
+</xsl:stylesheet>
\ No newline at end of file
Index: webapp/cms/plugins/ugc/stylesheets/content/simpleContent/simpleContent.xsl
===================================================================
--- webapp/cms/plugins/ugc/stylesheets/content/simpleContent/simpleContent.xsl	(revision 0)
+++ webapp/cms/plugins/ugc/stylesheets/content/simpleContent/simpleContent.xsl	(revision 0)
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2010 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+   
+<!-- Copy from plugins/web/stylesheets/content/article -->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
+							  xmlns:docbook="http://docbook.org/ns/docbook" 
+                              xmlns:i18n="http://apache.org/cocoon/i18n/2.1" 
+                              xmlns:resolver="org.ametys.cms.transformation.xslt.ResolveURIComponent" 
+                              exclude-result-prefixes="docbook resolver">
+	
+    <xsl:import href="service:web://stylesheets/content/common.xsl"/>
+	
+    <!-- Used in common.xsl -->
+    <xsl:variable name="common-content-css-class-name">article view-main</xsl:variable>     
+    <xsl:variable name="common-content-name">article</xsl:variable>
+    
+    <!-- +
+         | HEAD
+         + -->
+
+    <!-- Used in common.xsl -->
+    <xsl:template name="common-content-head-title">
+        <xsl:call-template name="common-content-head-title-content"/>
+    </xsl:template> 
+
+    <!-- +
+         | BODY
+         + -->
+    <!-- Used in common.xsl -->
+    <xsl:template name="common-content-body-title">
+        <xsl:call-template name="common-content-body-title-content"/>
+    </xsl:template>     
+    
+    <xsl:template name="common-content-body-content">
+        <!-- Image -->
+        <xsl:call-template name="common-content-body-image-bigsize"/>    
+    
+        <!-- Rich content -->
+        <xsl:call-template name="common-content-body-content-rich"/>
+        
+        <div class="content-richtext-end"><xsl:comment>empty</xsl:comment></div>
+        
+        <!-- Contact, Publish date... -->
+        <xsl:call-template name="common-content-body-meta"/>        
+
+        <!-- Comments -->
+        <xsl:call-template name="common-content-body-comments"/>
+    </xsl:template>
+	
+</xsl:stylesheet>
Index: webapp/cms/plugins/ugc/stylesheets/content/simpleContent/simpleContent2pdf-main.xsl
===================================================================
--- webapp/cms/plugins/ugc/stylesheets/content/simpleContent/simpleContent2pdf-main.xsl	(revision 0)
+++ webapp/cms/plugins/ugc/stylesheets/content/simpleContent/simpleContent2pdf-main.xsl	(revision 0)
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2010 Anyware Services
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   -->
+   
+<!-- Copy from plugins/web/stylesheets/content/article -->
+   
+<xsl:stylesheet version="1.0"
+	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns:docbook="http://docbook.org/ns/docbook"
+	xmlns:i18n="http://apache.org/cocoon/i18n/2.1"
+	xmlns:fo="http://www.w3.org/1999/XSL/Format"
+    xmlns:resolver="org.ametys.cms.transformation.xslt.ResolveURIComponent"
+    xmlns:decoder="org.ametys.cms.transformation.xslt.URIDecoder"
+    xmlns:cms="http://ametys.org/cms/3.0"
+    exclude-result-prefixes="docbook"
+    extension-element-prefixes="resolver decoder cms">
+
+    <xsl:import href="plugin:cms://stylesheets/helper/common.xsl"/>
+	<xsl:import href="plugin:web://stylesheets/docbook2fo.xsl" />
+
+	<xsl:param name="contextPath" />
+	<xsl:param name="siteName" />
+	<xsl:param name="skin" />
+
+	<xsl:template match="/">
+		<fo:root>
+			<fo:layout-master-set>
+				<fo:simple-page-master master-name="page"
+					page-width="210mm" page-height="297mm" margin-left="0cm"
+					margin-right="0cm" margin-top="0cm" margin-bottom="0cm">
+					<fo:region-body margin-top="3cm" margin-bottom="1cm">
+                        <xsl:call-template name="region-body-definition"/>
+                    </fo:region-body>
+					<fo:region-before extent="0cm">
+                        <xsl:call-template name="region-before-definition"/>
+                    </fo:region-before>
+					<fo:region-after extent="0cm">
+                        <xsl:call-template name="region-after-definition"/>
+                    </fo:region-after>
+				</fo:simple-page-master>
+			</fo:layout-master-set>
+			
+			<xsl:apply-templates />
+		</fo:root>
+	</xsl:template>
+	
+	<xsl:template name="xsl-region-before">
+	</xsl:template>
+
+	<xsl:template match="content">
+		<fo:page-sequence master-reference="page">
+			
+			<xsl:call-template name="xsl-region-before"/>
+			
+			<fo:flow flow-name="xsl-region-body">
+				<fo:block margin-left="1cm" margin-right="1cm">
+                    <xsl:call-template name="main-body-block"/>
+                    
+					<fo:block>
+						<xsl:call-template name="title-style">
+       						<xsl:with-param name="level" select="2"/>
+       					</xsl:call-template>
+       					
+						<xsl:value-of select="metadata/title" />
+                        
+                        <xsl:if test="metadata/document-subtitle != ''">
+                            <fo:block>
+                                <xsl:call-template name="subtitle-style">
+                                    <xsl:with-param name="level" select="2"/>
+                                </xsl:call-template>
+                                
+                                <xsl:value-of select="metadata/document-subtitle" />
+                            </fo:block>
+                        </xsl:if>
+					</fo:block>
+
+					<fo:block>
+						
+						<xsl:if test="metadata/illustration/image">
+							<xsl:call-template name="content-illustration"/>
+						</xsl:if>
+							
+						<xsl:if test="cms:isNotRichTextEmpty(metadata/content)">
+							<xsl:apply-templates select="metadata/content/docbook:article">
+								<xsl:with-param name="level" select="3"/>
+							</xsl:apply-templates>
+						</xsl:if>
+					</fo:block>
+				</fo:block>
+			</fo:flow>
+		</fo:page-sequence>
+	</xsl:template>
+	
+	<xsl:template name="content-illustration">
+		<fo:external-graphic src="{decoder:decode(resolver:resolveBoundedImage(metadata/illustration/image/@type, metadata/illustration/image/@path, 150, 150, false(), false(), true()))}">
+			<xsl:call-template name="image-style">
+				<xsl:with-param name="class" select="'illustration'"/>
+			</xsl:call-template>
+		</fo:external-graphic>
+	</xsl:template>
+	
+	<!-- +
+	     | Default style
+	     + -->
+    <xsl:template name="region-body-definition"/>
+    
+    <xsl:template name="region-before-definition"/>
+    
+    <xsl:template name="region-after-definition"/>
+    
+    <xsl:template name="main-body-block"/>
+    
+    <xsl:template name="content-body-style"/>
+    
+	<xsl:template name="para-style">
+		<xsl:param name="class"/>
+	</xsl:template>
+	
+	<xsl:template name="subscript">
+	</xsl:template>
+	
+	<xsl:template name="supscript">
+	</xsl:template>
+	
+	<xsl:template name="title-style">
+		<xsl:param name="level"/>
+	</xsl:template>
+	
+	<xsl:template name="image-style">
+		<xsl:param name="class"/>
+	</xsl:template>
+	
+	<xsl:template name="image-caption">
+	</xsl:template>
+	
+	<xsl:template name="link-style">
+		<xsl:param name="class"/>
+	</xsl:template>
+	
+	<xsl:template name="link-href-style">
+	</xsl:template>
+	
+	<xsl:template name="table-style">
+		<xsl:param name="class"/>
+	</xsl:template>
+	
+	<xsl:template name="table-caption"/>
+	
+	<xsl:template name="tr-style">
+		<xsl:param name="class"/>
+	</xsl:template>
+	     
+	<xsl:template name="th-style">
+		<xsl:param name="class"/>
+	</xsl:template>
+	
+	<xsl:template name="td-style">
+		<xsl:param name="class"/>
+	</xsl:template>
+	
+	<xsl:template name="ol-style">
+		<xsl:param name="mark"/>
+	</xsl:template>
+	
+	<xsl:template name="ul-style">
+		<xsl:param name="mark"/>
+	</xsl:template>
+	
+</xsl:stylesheet>
